了解Crockford介绍的优越方法

tar*_*lah 3 javascript javascript-objects

在功能继承模式中,Crockford superior通过以下方式引入了一种新方法:

Object.method('superior', function (name) {
    var that = this,
    method = that[name];
    return function () {
        return method.apply(that, arguments);
    };
});
Run Code Online (Sandbox Code Playgroud)

在哪里method:

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};
Run Code Online (Sandbox Code Playgroud)

例:

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;
};
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么不分配that.get_namesuper_get_name

coo*_*ter 7

"我的问题是为什么不分配that.get_namesuper_get_name谁?"

因为get_name方法将其this值设置为that对象的方式是通过调用它:

that.get_name();
Run Code Online (Sandbox Code Playgroud)

当函数作为对象的方法被调用时,该对象将成为this该函数调用的值.

如果你这样做了:

var super_get_name = that.get_name;

super_get_name();
Run Code Online (Sandbox Code Playgroud)

现在你正在调用一个分离的函数,因此它不知道它的this值应该是什么,因此它使用默认值,通常是window对象.


我不喜欢crockford所展示的解决方案.通常,在这种情况下,您只需在那里创建一个新功能,而不是依赖扩展来Object.prototype为您完成.(扩展Object.prototype是非常丑陋的IMO.)

var coolcat = function (spec) {
    var that = cat(spec),
        _original_get_name = that.get_name,
        super_get_name = function() {
                             return _original_get_name.apply(that, arguments);
                         };

    that.get_name = function (n) {
        return 'like ' + super_get_name() + ' baby';
    };
    return that;
};
Run Code Online (Sandbox Code Playgroud)

或者在现代实现中,您将使用Function.prototype.bind创建一个新函数,其this值绑定到您作为第一个参数提供的任何值.bind().

var coolcat = function (spec) {
    var that = cat(spec),
        super_get_name = that.get_name.bind(that);

    that.get_name = function (n) {
        return 'like ' + super_get_name() + ' baby';
    };
    return that;
};
Run Code Online (Sandbox Code Playgroud)