背景作者:陳大魚(yú)頭
github: KRISACHAN
在最近的項(xiàng)目中,有這么一個(gè)功能點(diǎn),就是要獲取在WEB IDE里用戶(hù)所寫(xiě)的注釋中的一段特殊規(guī)則,然后解析成一段JS config 對(duì)象
例如:
//% width="100px" height="200px"
//% pos.top="50px" pos.left="50px"
//% writable=true
//% q.b.d.w.r.f=30 q.b.d.w.r.a=40
要轉(zhuǎn)成
{
width: "100px",
height: "200px",
pos: {
top: "50px",
left: "50px"
},
writable: true,
q: {
b: {
d: {
w: {
r: {
f: 30,
a: 40
}
}
}
}
}
}
類(lèi)似的規(guī)則
什么是遞歸
來(lái)自百度的解釋?zhuān)?
遞歸:程序調(diào)用自身的編程技巧稱(chēng)為遞歸 (recursion)
尾遞歸:如果一個(gè)函數(shù)中所有遞歸形式的調(diào)用都出現(xiàn)在函數(shù)的末尾,我們稱(chēng)這個(gè)遞歸函數(shù)是尾遞歸的。
就是 復(fù)讀機(jī)
遞歸怎么寫(xiě)?
一般
const fibonacci = num => (num === 1 ");
尾遞歸
const fibonacci = (num, total = 1) => (num === 0 ");
Array.reduce
const getArray = count => Array.from({ length: count }, (value, key) => key) const fibonacci = num => getArray(num).reduceRight((accumulator, currentValue) => accumulator * currentValue)功能實(shí)現(xiàn) 分步實(shí)現(xiàn)
過(guò)濾常規(guī)內(nèi)容,獲取特殊的備注信息,去除空格,并且轉(zhuǎn)成數(shù)組
此時(shí)的數(shù)組內(nèi)容為
[
"http://% blockId="sloth_servo_write" block="set servo %channel|degree %degree"",
"http://% advanced=true",
"http://% weight=50",
"http://% degree.min=0 degree.max=180",
"http://% channel.fieldEditor="gridpicker" channel.fieldOptions.columns=4",
"http://% a.b.c.d=20 a.b.c.e=222",
"http://% q.b.d.w.r.f=30 q.b.d.w.r.a=40"
]
const code = `
//% width="100px" height="200px"
//% pos.top="50px" pos.left="50px"
//% writable=true
//% q.b.d.w.r.f=30 q.b.d.w.r.a=40`
// 獲取特殊注釋數(shù)組
const annotation_array_filter = annotation_item => annotation_item.indexOf("http://%") >= 0;
// 去除特殊注釋前后的空格
const annotation_array_remove_space = annotation_item => annotation_item.trim();
const annotation_array = code.split("
")
.filter(annotation_array_filter)
.map(annotation_array_remove_space)
遍歷特殊規(guī)則數(shù)組,把每一項(xiàng)配置都?jí)喝胍粋€(gè)新對(duì)象
此時(shí)的新對(duì)象內(nèi)內(nèi)容為
{
a.b.c.d: 20,
a.b.c.e: 222,
advanced: true,
block: "set servo %channel|degree %degree",
blockId: "sloth_servo_write",
channel.fieldEditor: "gridpicker",
channel.fieldOptions.columns: 4,
degree.max: 180,
degree.min: 0,
q.b.d.w.r.a: 40,
q.b.d.w.r.f: 30,
weight: 50,
}
const annotation_array_loop = annotation_item => {
// 把注釋中的每一項(xiàng)配置轉(zhuǎn)成對(duì)象
const result_forEach = result_item => {
let annotation_sub_object = {};
// 如果特殊注釋數(shù)組中的每一項(xiàng)包含多個(gè)配置,則扁平化
const array_flattened = data => {
const is_array = (this.type(data) === "[object Array]");
const object_recursion = () => {
const [key, value] = data.split("=");
const annotation_sub_object = {};
try {
annotation_sub_object[key] = JSON.parse(value);
} catch (error) {
annotation_sub_object[key] = JSON.parse(value + """)
};
annotation_object = {
...annotation_object,
...annotation_sub_object
};
};
// 判斷注釋數(shù)組項(xiàng)中每一個(gè)元素是否有多個(gè)配置,如果有則遞歸,否則則注入對(duì)象
is_array ");" ") : result_item);
const result = annotation_item.replace("http://% ", "")
.split("/" /g")
.map(result_map);
result_forEach(result);
};
let annotation_object = {}; // 承載每一個(gè)配置的對(duì)象
annotation_array.forEach(annotation_array_loop);
把數(shù)組里的元素轉(zhuǎn)成對(duì)象
此時(shí)數(shù)組內(nèi)容為
[
{
blockId: "sloth_servo_write"
},
{
advanced: true
},
...
]
let main_array = []; // 承載每一個(gè)配置的數(shù)組
const annotation_object_keys = Object.keys(annotation_object); // 獲取扁平化后的注釋對(duì)象的key
const annotation_object_keys_loop = annotation_object_key => { // 循環(huán)變量每一項(xiàng)注釋
const annotation_object_key_array = annotation_object_key.split("."); // 把多級(jí)對(duì)象轉(zhuǎn)成數(shù)組
const annotation_object_value = annotation_object[annotation_object_key]; // 獲取每一項(xiàng)元素的值
let sub_object = {}; // 暫時(shí)承載配置對(duì)象的對(duì)象
const key_reduce = (accumulator, current_value, current_index, array) => { // key值遞歸,對(duì)每一項(xiàng)配置進(jìn)行合并
if (current_index === 0) { // 如果當(dāng)前遍歷的元素為第一項(xiàng),也就是說(shuō)為配置的頂級(jí)對(duì)象,所以直接壓入對(duì)象,并且輸出
sub_object[current_value] = (current_index === array.length - 1 ");return sub_object[current_value];
}
accumulator[current_value] = {}; // 如果當(dāng)前遍歷的元素不為第一項(xiàng),則當(dāng)前對(duì)象元素變?yōu)閷?duì)象
if (current_index === array.length - 1) { // 如果當(dāng)前遍歷的元素為數(shù)組最后一項(xiàng),說(shuō)明是配置對(duì)象最底的元素,可以直接賦值
accumulator[current_value] = annotation_object_value;
}
return accumulator[current_value];
};
let level_object = annotation_object_key_array.reduce(key_reduce, annotation_object_key_array[0]);
level_object = undefined; // 清空l(shuí)evel_object
main_array.push(sub_object);
sub_object = undefined; // 清空sub_object
}
annotation_object_keys.forEach(annotation_object_keys_loop);
遞歸合并對(duì)象
此時(shí)的對(duì)象為
{
a: {b: {…}},
advanced: true,
block: "set servo %channel|degree %degree",
blockId: "sloth_servo_write",
channel: {fieldEditor: "gridpicker", fieldOptions: {…}},
degree: {min: 0, max: 180},
q: {b: {…}},
weight: 50
}
const annotation_tree = {};
const tree_data = (key, value, object) => { // 遞歸合并對(duì)象
if (this.type(value) !== "[object Object]") { // 如果當(dāng)前傳入元素為對(duì)象,則直接壓入對(duì)象中
object[key] = value;
} else { // 否則繼續(xù)遞歸
if (!object[key]) {
object[key] = {};
};
for (let item in value) {
tree_data(item, value[item], object[key]);
}
};
};
const main_array_forEach = item => { // 循環(huán)遍歷配置數(shù)組
const key = Object.keys(item)[0];
const value = Object.values(item)[0];
tree_data(key, value, annotation_tree);
};
main_array.forEach(main_array_forEach);
main_array = undefined; // 清空main_array
完整代碼
// 代碼轉(zhuǎn)換器
((wid, dcm) => {
"use strict";
const win = wid;
const doc = dcm;
// 基礎(chǔ)信息
const base_info = {
"version": "0.0.1",
"author": "kris",
};
// 輸出的函數(shù)
const funcs = {
annotation_parser (annotation) {
// 配置樹(shù)初始化
this.annotation_tree = {};
// 獲取特殊注釋數(shù)組
const annotation_array_filter = annotation_item => annotation_item.indexOf("http://%") >= 0;
// 去除特殊注釋前后的空格
const annotation_array_remove_space = annotation_item => annotation_item.trim();
// 循環(huán)遍歷特殊注釋數(shù)組
const annotation_array_loop = annotation_item => {
// 把注釋中的每一項(xiàng)配置轉(zhuǎn)成對(duì)象
const result_forEach = result_item => {
let annotation_sub_object = {};
// 如果特殊注釋數(shù)組中的每一項(xiàng)包含多個(gè)配置,則扁平化
const array_flattened = data => {
const is_array = (this.type(data) === "[object Array]");
const object_recursion = () => {
const [key, value] = data.split("=");
const annotation_sub_object = {};
try {
annotation_sub_object[key] = JSON.parse(value);
} catch (error) {
annotation_sub_object[key] = JSON.parse(value + """)
};
annotation_object = {
...annotation_object,
...annotation_sub_object
};
};
// 判斷注釋數(shù)組項(xiàng)中每一個(gè)元素是否有多個(gè)配置,如果有則遞歸,否則則注入對(duì)象
is_array ");" ") : result_item);
const result = annotation_item.replace("http://% ", "")
.split("/" /g")
.map(result_map);
result_forEach(result);
};
let annotation_object = {}; // 承載每一個(gè)配置的對(duì)象
annotation.filter(annotation_array_filter)
.map(annotation_array_remove_space)
.forEach(annotation_array_loop);
let main_array = []; // 承載每一個(gè)配置的數(shù)組
const annotation_object_keys = Object.keys(annotation_object); // 獲取扁平化后的注釋對(duì)象的key
const annotation_object_keys_loop = annotation_object_key => { // 循環(huán)變量每一項(xiàng)注釋
const annotation_object_key_array = annotation_object_key.split("."); // 把多級(jí)對(duì)象轉(zhuǎn)成數(shù)組
const annotation_object_value = annotation_object[annotation_object_key]; // 獲取每一項(xiàng)元素的值
let sub_object = {}; // 暫時(shí)承載配置對(duì)象的對(duì)象
const key_reduce = (accumulator, current_value, current_index, array) => { // key值遞歸,對(duì)每一項(xiàng)配置進(jìn)行合并
if (current_index === 0) { // 如果當(dāng)前遍歷的元素為第一項(xiàng),也就是說(shuō)為配置的頂級(jí)對(duì)象,所以直接壓入對(duì)象,并且輸出
sub_object[current_value] = (current_index === array.length - 1 ");return sub_object[current_value];
}
accumulator[current_value] = {}; // 如果當(dāng)前遍歷的元素不為第一項(xiàng),則當(dāng)前對(duì)象元素變?yōu)閷?duì)象
if (current_index === array.length - 1) { // 如果當(dāng)前遍歷的元素為數(shù)組最后一項(xiàng),說(shuō)明是配置對(duì)象最底的元素,可以直接賦值
accumulator[current_value] = annotation_object_value;
}
return accumulator[current_value];
};
let level_object = annotation_object_key_array.reduce(key_reduce, annotation_object_key_array[0]);
level_object = undefined; // 清空l(shuí)evel_object
main_array.push(sub_object);
sub_object = undefined; // 清空sub_object
}
annotation_object_keys.forEach(annotation_object_keys_loop);
const tree_data = (key, value, object) => { // 遞歸合并對(duì)象
if (this.type(value) !== "[object Object]") { // 如果當(dāng)前傳入元素為對(duì)象,則直接壓入對(duì)象中
object[key] = value;
} else { // 否則繼續(xù)遞歸
if (!object[key]) {
object[key] = {};
};
for (let item in value) {
tree_data(item, value[item], object[key]);
}
};
};
const main_array_forEach = item => { // 循環(huán)遍歷配置數(shù)組
const key = Object.keys(item)[0];
const value = Object.values(item)[0];
tree_data(key, value, this.annotation_tree);
};
main_array.forEach(main_array_forEach);
main_array = undefined; // 清空main_array
},
};
// 引用的資源
const libs = {};
// 工具函數(shù)
const tools = {
// 獲取元素類(lèi)型
type (object) {
return Object.prototype.toString.call(object);
},
// 分離傳入的代碼跟配置
separate_code_and_config (data) {
data.split("
")
.forEach(item => {
item.indexOf("http://%") >= 0 ");return this || (0, eval)("this");
})();
if (typeof module !== "undefined" && module.exports) {
module.exports = code_transformer;
} else if (typeof define === "function" && define.amd) {
define([], function () {
return code_transformer;
});
} else {
!("code_transformer" in _global) && (_global.code_transformer = code_transformer);
};
})(window, document);
備注:函數(shù)體積好大呀,但這只是業(yè)務(wù)里的一個(gè)小小小功能,流下了不會(huì)優(yōu)化代碼的淚水~
如果你、喜歡探討技術(shù),或者對(duì)本文有任何的意見(jiàn)或建議,你可以?huà)呙柘路蕉S碼,關(guān)注微信公眾號(hào)“魚(yú)頭的Web海洋”,隨時(shí)與魚(yú)頭互動(dòng)。歡迎!衷心希望可以遇見(jiàn)你。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/6931.html
摘要:做這個(gè)記錄之前,剛完成使用作為公司前端項(xiàng)目的持續(xù)交付工具的實(shí)踐,打算寫(xiě)的教程前先把官方文檔扒下來(lái)做個(gè)翻譯站。在實(shí)踐一番后,卡在不能頻密調(diào)取翻譯這塊上,項(xiàng)目無(wú)法進(jìn)行下去。 做這個(gè)記錄之前,剛完成使用drone作為公司前端項(xiàng)目的持續(xù)交付工具的實(shí)踐,打算寫(xiě)的教程前先把官方文檔扒下來(lái)做個(gè)翻譯站。在實(shí)踐一番后,卡在不能頻密調(diào)取google翻譯這塊上,項(xiàng)目無(wú)法進(jìn)行下去。最后覺(jué)得經(jīng)歷的過(guò)程涉及的內(nèi)容...
摘要:面試官說(shuō)那我問(wèn)你一個(gè)哲學(xué)的問(wèn)題,為什么有數(shù)據(jù)結(jié)構(gòu)這種東西哇,這是啥,巴拉巴拉扯了一通,大致就是物以類(lèi)聚,人以群分,先人積累下來(lái)的經(jīng)驗(yàn),這些讓我們更方便處理數(shù)據(jù)啥的。 前因,沒(méi)有比摸魚(yú)有趣的事了 距離自己被外派(俗稱(chēng)外包)出去,已經(jīng)過(guò)了快五個(gè)月,工作的話(huà),很閑。人啊,一定保持好的習(xí)慣,懶惰是會(huì)上癮,日常摸魚(yú),懷疑人生,我是誰(shuí),我在哪,我要干什么。 中午吃飯的時(shí)候,收到了boss直聘的一條...
摘要:手頭做的項(xiàng)目開(kāi)發(fā)得差不多了,而打包配置是一開(kāi)始粗略配置的,不大的項(xiàng)目打包出來(lái)得,所以現(xiàn)在必須進(jìn)行優(yōu)化。用于生產(chǎn)環(huán)境的打包,設(shè)置其為后,這些庫(kù)會(huì)提供最小體積的文件。這種情況打包后的體積要更小一些。最后打包結(jié)果的體積開(kāi)銷(xiāo)主要就是以上幾項(xiàng)。 手頭做的項(xiàng)目開(kāi)發(fā)得差不多了,而打包配置是一開(kāi)始粗略配置的,不大的項(xiàng)目打包出來(lái)得6MB+,所以現(xiàn)在必須進(jìn)行優(yōu)化。 打包結(jié)果分析 執(zhí)行命令 webpack ...
摘要:之所以在本地構(gòu)建,而沒(méi)有使用倉(cāng)庫(kù)的,是因?yàn)椋覀兊溺R像采用了國(guó)內(nèi)阿里云的源,再加上某些很奇妙的網(wǎng)絡(luò)因素,在中自動(dòng)構(gòu)建時(shí),升級(jí)總會(huì)失敗。然而,在本地再次構(gòu)建成功。 見(jiàn)字如晤。 前段時(shí)間,Node.js 官方發(fā)布了Node 8.9.3 LTS版本,并且官網(wǎng)首頁(yè)提示新版本有重要安全更新,Important security releases, please update now! ,然后我立...
閱讀 3333·2021-11-23 09:51
閱讀 2460·2021-11-09 09:46
閱讀 1493·2019-08-30 15:54
閱讀 3147·2019-08-30 14:22
閱讀 2920·2019-08-29 12:40
閱讀 1645·2019-08-26 10:33
閱讀 1790·2019-08-23 17:09
閱讀 1566·2019-08-23 16:11