Javascript 理解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 =

在功能继承模式中,Crockford通过以下方式引入了一种新的
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();