Javascript 理解Crockford介绍的优越方法
在功能继承模式中,Crockford通过以下方式引入了一种新的Javascript 理解Crockford介绍的优越方法,javascript,javascript-objects,Javascript,Javascript Objects,在功能继承模式中,Crockford通过以下方式引入了一种新的superior方法: Object.method('superior', function (name) { var that = this, method = that[name]; return function () { return method.apply(that, arguments); }; }); 其中方法为: Function.prototype.method =
superior
方法:
Object.method('superior', function (name) {
var that = this,
method = that[name];
return function () {
return method.apply(that, arguments);
};
});
其中方法
为:
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
示例:
var coolcat = function (spec) {
var that = cat(spec),
super_get_name = that.superior('get_name');
that.get_name = function (n) {
return 'like ' + super_get_name() + ' baby';
};
return that;
};
我的问题是,为什么不把
分配给它呢。get\u name
分配给super\u get\u name
?superior
是在对象构造函数的原型中定义的一种方法。它缓存一个对象的方法,这样即使它后来被更改,它也会返回原始方法
摘自JavaScript:好的部分,第54页:
即使属性发生更改,函数也将调用原始方法
“我的问题是为什么不把分配给super\u get\u name
?”
因为get\u name
方法将其this
值设置为对象的方式是通过调用它作为:
that.get_name();
当函数作为对象的方法调用时,该对象将成为该函数调用中的this
的值
如果您已经这样做了:
var super_get_name = that.get_name;
super_get_name();
现在您正在调用一个分离的函数,因此它不知道它的这个
值应该是什么,因此它使用默认值,通常是窗口
对象
我一点也不喜欢crockford展示的解决方案。通常,在这种情况下,您只需在此处创建一个新函数,而不需要依赖对Object.prototype
的扩展即可。(扩展Object.prototype
在我看来非常难看。)
或者在现代实现中,您可以使用Function.prototype.bind
创建一个新函数,其值绑定到作为.bind()的第一个参数提供的任何值
在Crockford函数继承模式的意义上,引用基类方法是完全有效的
var super_get_name = that.get_name;
这是Crockford在他的书中教授的,请参见功能继承部分。
稍后-该方法可能会被派生类重写-您只需调用它即可
super_get_name();
Crockford的superior
方法在函数继承模式中毫无意义
因为在我看来,在生产者函数定义的方法中,这个
是不需要的。如果您在方法中使用this
,您将遇到各种各样的麻烦,因为this
的动态作用域和操作:
function mammal(spec){
var that = {};
that.legs = Math.round(Math.random() * 4);
that.get_name = function(){
return spec.name + "with" + that.legs; // always use that not this
};
that.isProperThis = function(){
console.log( this === that );
};
return that;
};
var myMammal = mammal({name: 'Herb'});
myMammal.isProperThis(); // true
myMammal.isProperThis.call(window); // false
setTimeout(myMammal.isProperThis, 1); // false
如果您坚持在方法中使用this
,您就不能再将它们视为JavaScript中的“一流”变量。相反,你必须通过调用bind
将它们转换为“活页夹”,如本文第一个答案所述。cookie monster给出的公认答案是正确的,但我想补充说明
就像饼干怪兽说的,如果你写
var super_get_name = that.get_name;
调用super\u get\u name将不再将任何值绑定到此,使其成为未绑定函数
然而,在Crockford在好的部分给出的示例中,如果super\u get\u name以您提议的方式书写,则不受约束,因为这个永远不会在其调用中使用
您将基本上完成以下操作:
super_get_name = function () {
return that.says() + ' ' + spec.name +
' ' + that.says();
(其中右操作数在分配给cat的函数上下文中执行)
我假设Crockford在这里避免使用未绑定函数来演示一般原则,即使他的具体示例不需要绑定 谢谢你的bind
技巧,我也不喜欢hack。
var super_get_name = that.get_name;
super_get_name = function () {
return that.says() + ' ' + spec.name +
' ' + that.says();