最簡單的是绎签,通過一個key名來操作scope蛙埂。
var fn = parse('age');
fn({age:18})==18 //true
現(xiàn)在parse出來的fn是可以接受一個scope對象作為參數(shù)的,所以要改一下代碼
return Function('scope',this.state.body.join(' '));
這樣一來生成的函數(shù)就是這樣:
function (scope){.....}
接下來要擴充AST.primary方法都毒,使他可以處理identifier類型的token:
ASTBuilder.prototype.primary=function(){
if(ASTBuilder.Constants.hasOwnProperty(this.tokens[0].text)){
return ASTBuilder.Constants[this.consume().text];
}else if (this.expect("[")) {
return this.arrayDeclaration();
}else if (this.expect("{")) {
return this.object()
}else if (this.peek().identifier) {
return this.identifier()
}else{
return this.constant();
}
}
這樣一來粤蝎,產生的AST格式應該是這樣:
{
type:program,
body:{
type:ASTBuilder.Identifier,
name:'age'
}
}
下一步可以進入compile階段。
在recurse方法里面增加處理Identifier類型的節(jié)點:
case ASTBuilder.Identifier:
return 'scope.'+ast.name;//這里的scope和生成函數(shù)的參數(shù)對應function(scope){.....}
這樣走下來喇颁,沒意外的話漏健,生成的函數(shù)是可以通過測試案例的。經過測試橘霎,確實通過了蔫浆。第一步開了個好頭。
接下來是增加健壯性姐叁,如果執(zhí)行下面的測試案例瓦盛,目前的代碼會報錯:
it('通過name操作對象',function () {
var fn = parse('age');
expect(fn()).toBe(18);
})
如果要是能在生成的函數(shù)里面加上這么一段代碼,就可以了:
function (scope){
var v0;
if(scope){
v0= scope.age;
}
return v0;
}
先寫一個輔助方法外潜,用于給生成的函數(shù)增加一個if語句:
Compiler.prototype.if_=function(test,consequent){
this.state.body.push('if(',test,')','{',consequent,'}');
}
利用這個函數(shù)改造compile方法:
case ASTBuilder.Identifier:
this.state.body.push('var v0;');
this.if_('scope','v0='+'scope.'+ast.name+';')//這里的scope和生成函數(shù)的參數(shù)對應function(scope){.....}
return 'v0';
這段代碼看起來很復雜原环,其實用腦子用心好好看一看,腦子里想一想代碼是怎么跑的处窥,其實很容易理解嘱吗。
接下來的事情就是把代碼美化一下了。先寫一個工具函數(shù)滔驾,用于生成一個賦值語句:
Compiler.prototype.assign=function(id,value){
return id+'='+value+';';
}
把compile里面那一段臟亂差的代碼美化一下:
this.if_('scope',this.assign('v0','scope'+ast.name))//這里的scope和生成函數(shù)的參數(shù)對應function(scope){.....}
好了谒麦,今天大概就寫到這吧俄讹。