這幾天在升級自己的MVVM 框架,遇到很多小問題,就在這裡統一解決了.
在代碼中,要執行這麼一個函數
functioncomputeExpression(exp, scope) {
try {
with (scope) {
return eval(exp);
}
} catch (e) {
console.error('ERROR', e);
}
}
要求在scope 作用域中執行,什麼意思???
比如
scope = {a:10,b:5};
exp = a*b;
要求計算結果為15,這種情況,常規情況下要使用 with語法。
但是:
js的解釋器需要檢查with塊中的變量是否屬於with包含的對象,這將使with語句執行速度大大下降,並且導致js語句很難被優化。
在嚴格模式中,with語法是被禁用的。
而我使用ES6語法來編寫這個庫的,默認啟用了嚴格模式了。所以不得已,自己模擬了一個with 的語法。
先看代碼
functionreplaceWith(scopeName, exp) {
exp = " " + exp.trim();
let quickRegex = /([\s\+\-\*\/%&\|\^!\*~]\s*?)([a-zA-Z_$][a-zA-Z_$0-9]*?)/g;
exp = exp.replace(quickRegex, (a, b, c) => {
return b + scopeName + '.' + c;
});
return exp;
}
首先把首位的空格全部去掉,為了和後面的統一,在開頭加上一個空格。
第一個正則匹配出猶如"t.e==0 ? f : d"
的表達式中的變量
會被作為c
提取出來,符號作為 b
提取出來。
測試一下
現在已經可以返回一個表達式了,改裝一下,讓表達式直接在裡面執行
functionreplaceWith(scope, exp) {
exp = " " + exp.trim();
let quickRegex = /([\s\+\-\*\/%&\|\^!\*~]\s*?)([a-zA-Z_$][a-zA-Z_$0-9]*?)/g;
exp = exp.replace(quickRegex, (a, b, c) => {
return b + 'scope.' + c;
});
let func = new Function("scope", "return " + exp);
return func(scope);
}
測試一下
大功告成。
可能中間正則寫的不好,還有其他不嚴密的地方,歡迎園友補充。
好久都沒怎麼寫過大量代碼了,看到 Sring.prototype.split(//); 這個正則表達式,竟然把分割符號都給加到數組中了,很驚訝,在MDN上學了一下。順便做個整理,算是補充吧。
separator:指定用來分割字符串的字符(串)。separator 可以是一個字符串或正則表達式。 如果忽略 separator,則返回整個字符串的數組形式。如果 separator 是一個空字符串,則 str 將會把原字符串中每個字符的數組形式返回。
limit一個整數,限定返回的分割片段數量。split 方法仍然分割每一個匹配的 separator,但是返回的數組只會截取最多 limit 個元素。
當找到一個 seperator 時,separator 會從字符串中被移除,返回存進一個數組當中的子字符串。如果忽略 separator 參數,則返回的數組包含一個元素,該元素是原字符串。如果 separator 是一個空字符串,則 str 將被轉換為由字符串中字符組成的一個數組。
注意:
var myString = "hello world";
var splits = myString.split(();
console.log(splits);
輸出
["hello world"]
var myString = "Hello 1 word. Sentence number 2.";
var splits = myString.split(/(\d)/);
console.log(splits);
輸出
Hello ,1, word. Sentence number ,2,.
這個方法開始已經用到,就不再介紹。
當字符串匹配到正則表達式(regular expression)時,match() 方法會提取匹配項。
如果正則表達式沒有 g 標志,返回和 RegExp.exec(str) 相同的結果。而且返回的數組擁有一個額外的 input 屬性,該屬性包含原始字符串。另外,還擁有一個 index 屬性,該屬性表示匹配結果在原字符串中的索引(以0開始)。
"1aef2af3ef4 5".match(/[a-z]*(\d)/)
輸出
["1", "1"]
如果正則表達式包含 g 標志,則該方法返回一個包含所���匹配結果的數組。如果沒有匹配到,則返回 null。
注意,如果加g, 則分組無用
"1aef2af3ef4 5".match(/[a-z]*(\d)/g)
輸出
["1", "aef2", "af3", "ef4", "5"]
search() 方法執行一個查找,看該字符串對象與一個正則表達式是否匹配。
如果匹配成功,則 search() 返回正則表達式在字符串中首次匹配項的索引。否則,返回 -1。
類似於正則表達式的 test 方法 。
"aeg56".search(/[a-z]\d+/)
輸出
2