mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-11 16:23:09 +00:00
added compiled getterFN for better performance
This commit is contained in:
parent
1aa99c08e9
commit
2e33e89a77
4 changed files with 60 additions and 5 deletions
|
|
@ -25,7 +25,7 @@
|
||||||
<hr/>
|
<hr/>
|
||||||
<ul>
|
<ul>
|
||||||
<li ng-repeat="item in items.$filter('').$orderBy('name')">
|
<li ng-repeat="item in items.$filter('').$orderBy('name')">
|
||||||
{{item.name}} {{item.parts.join(', ')}}
|
{{item.name}} <a href="#{{item.name}}">{{item.parts.join(', ')}}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
|
|
@ -151,9 +151,7 @@ Lexer.prototype = {
|
||||||
}
|
}
|
||||||
var fn = Lexer.OPERATORS[ident];
|
var fn = Lexer.OPERATORS[ident];
|
||||||
if (!fn) {
|
if (!fn) {
|
||||||
fn = function(self){
|
fn = getterFn(ident);
|
||||||
return getter(self, ident);
|
|
||||||
};
|
|
||||||
fn.isAssignable = ident;
|
fn.isAssignable = ident;
|
||||||
}
|
}
|
||||||
this.tokens.push({index:start, text:ident, fn:fn});
|
this.tokens.push({index:start, text:ident, fn:fn});
|
||||||
|
|
@ -563,8 +561,9 @@ Parser.prototype = {
|
||||||
|
|
||||||
fieldAccess: function(object) {
|
fieldAccess: function(object) {
|
||||||
var field = this.expect().text;
|
var field = this.expect().text;
|
||||||
|
var getter = getterFn(field);
|
||||||
var fn = function (self){
|
var fn = function (self){
|
||||||
return getter(object(self), field);
|
return getter(object(self));
|
||||||
};
|
};
|
||||||
fn.isAssignable = field;
|
fn.isAssignable = field;
|
||||||
return fn;
|
return fn;
|
||||||
|
|
|
||||||
35
src/Scope.js
35
src/Scope.js
|
|
@ -43,6 +43,41 @@ function setter(instance, path, value){
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////
|
||||||
|
|
||||||
|
var getterFnCache = {};
|
||||||
|
function getterFn(path){
|
||||||
|
var fn = getterFnCache[path];
|
||||||
|
if (fn) return fn;
|
||||||
|
|
||||||
|
var code = 'function (self){\n';
|
||||||
|
code += ' var last, fn, type;\n';
|
||||||
|
foreach(path.split('.'), function(key) {
|
||||||
|
code += ' if(!self) return self;\n';
|
||||||
|
code += ' last = self;\n';
|
||||||
|
code += ' self = self.' + key + ';\n';
|
||||||
|
code += ' if(typeof self == "function") \n';
|
||||||
|
code += ' self = function(){ return last.'+key+'.apply(last, arguments); };\n';
|
||||||
|
if (key.charAt(0) == '$') {
|
||||||
|
// special code for super-imposed functions
|
||||||
|
var name = key.substr(1);
|
||||||
|
code += ' if(!self) {\n';
|
||||||
|
code += ' type = angular.Global.typeOf(last);\n';
|
||||||
|
code += ' fn = (angular[type.charAt(0).toUpperCase() + type.substring(1)]||{})["' + name + '"];\n';
|
||||||
|
code += ' if (fn)\n';
|
||||||
|
code += ' self = function(){ return fn.apply(last, [last].concat(slice.call(arguments, 0, arguments.length))); };\n';
|
||||||
|
code += ' }\n';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
code += ' return self;\n}';
|
||||||
|
fn = eval('(' + code + ')');
|
||||||
|
fn.toString = function(){ return code; };
|
||||||
|
|
||||||
|
return getterFnCache[path] = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////
|
||||||
|
|
||||||
var compileCache = {};
|
var compileCache = {};
|
||||||
function expressionCompile(exp){
|
function expressionCompile(exp){
|
||||||
if (isFunction(exp)) return exp;
|
if (isFunction(exp)) return exp;
|
||||||
|
|
|
||||||
|
|
@ -157,4 +157,25 @@ describe('scope/model', function(){
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getterFn', function(){
|
||||||
|
it('should get chain', function(){
|
||||||
|
expect(getterFn('a.b')(undefined)).toEqual(undefined);
|
||||||
|
expect(getterFn('a.b')({})).toEqual(undefined);
|
||||||
|
expect(getterFn('a.b')({a:null})).toEqual(undefined);
|
||||||
|
expect(getterFn('a.b')({a:{}})).toEqual(undefined);
|
||||||
|
expect(getterFn('a.b')({a:{b:null}})).toEqual(null);
|
||||||
|
expect(getterFn('a.b')({a:{b:0}})).toEqual(0);
|
||||||
|
expect(getterFn('a.b')({a:{b:'abc'}})).toEqual('abc');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should map type method on top of expression', function(){
|
||||||
|
expect(getterFn('a.$filter')({a:[]})('')).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should bind function this', function(){
|
||||||
|
expect(getterFn('a')({a:function($){return this.b + $;}, b:1})(2)).toEqual(3);
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue