今天我看到了一个我不熟悉的JavaScript语法(在调用函数时)。它就像:
def('Person') ({
init: function(name) {this.name=name;}
,speak: function(text) {alert(text || 'Hi, my name is ' + this.name);}
});
和
def('Ninja') << Person ({
kick: function() {this.speak('I kick u!');}
});
1:第一个例子中括号内的对象会发生什么?它由def
函数以某种方式处理,但我不明白这里发生了什么(请参阅下面的def
函数)。对象在哪里?
2:关于同样的事情,但是使用了我从未见过的<<
运算符(我想!)。那是什么意思?
代码来自http://gist.github.com/474994,其中Joe Dalton做了一个小的JavaScript-OO继承事情(它显然是别人工作的一个分支,但看起来很彻底改写)。也许你想在那里查看def
函数引用的内容,我在这里给你:
function def(klassName, context) {
context || (context = global);
// Create class on given context (defaults to global object)
var Klass =
context[klassName] = function Klass() {
// Called as a constructor
if (this != context) {
// Allow the init method to return a different class/object
return this.init && this.init.apply(this, arguments);
}
// Called as a method
// defer setup of superclass and plugins
deferred._super = Klass;
deferred._plugins = arguments[0] || { };
};
// Add static helper method
Klass.addPlugins = addPlugins;
// Called as function when not
// inheriting from a superclass
deferred = function(plugins) {
return Klass.addPlugins(plugins);
};
// valueOf is called to set up
// inheritance from a superclass
deferred.valueOf = function() {
var Superclass = deferred._super;
if (!Superclass)
return Klass;
Subclass.prototype = Superclass.prototype;
Klass.prototype = new Subclass;
Klass.superclass = Superclass;
Klass.prototype.constructor = Klass;
return Klass.addPlugins(deferred._plugins);
};
return deferred;
}
答案 0 :(得分:13)
1:调用def('Person')
返回一个函数,该函数以对象作为参数调用。它的原理与:
function x() {
return function(y) { alert(y); }
}
x()('Hello world!');
2:<<
运算符是左移运算符。它将整数值向左移动特定的位数。我没有找到任何其他用途的参考,并且在Javascript中没有运算符重载,所以我无法理解在函数上使用它。到目前为止,它看起来像是一个错字。
正如Tim解释的那样,shift运算符仅用于引发对valueOf
方法的调用。它就像所有操作员的过载一样,接管了最初的目的并做了一些完全不同的事情。
答案 1 :(得分:5)
valueOf()
技巧。
使用:
创建"class"
的一般情况
def ("ClassName") ({
init: function() { .. },
foo: function() { .. }
});
是微不足道的,因为对def
的第一次调用返回一个接受一个对象的函数,并将传入的对象的属性复制到ClassName
的原型。
使用<<
子类的更有趣的情况依赖于表达式的求值顺序,以及通过对valueOf()
的隐式调用尝试将任何对象强制转换为值。基本技巧基本上是一个共享变量,它记录超类和要应用于它的属性。表达式,
def("ClassName") << ParentClass({ .. })
将按如下方式评估:
def("ClassName")
,并创建一个全局对象ClassName
并返回其构造函数。让我们调用这个返回的对象 - initializeMeLater
。ParentClass(..)
,它存储对ParentClass
的引用,以及传入的对象/属性在共享变量中。initializeMeLater.valueOf()
,它获取对父类的引用,以及该共享变量的属性,并设置原型。valueOf
在步骤2的返回值上被调用,这是无用的,没有效果,因为我们已经在步骤3中设置了超类关系。代码试图模拟用于创建子类的Ruby语法,如下所示:
class Child < Parent
def someMethod
...
end
end