网站搜索

Javascript 不会调用原型方法


我尝试重写一个方法,脚本是:

function wrapper(target) {
    target.doABC = function () {
        alert('in wrapper');
    };
    return target;
}

function Model() {
    wrapper(this);
}

Model.prototype.doABC = function () {
    alert('in Model');
};

var a = new Model();
a.doABC();

结果是 'in wrapper'。我不知道为什么?

答案#1

任何 JavaScript 对象都有 自身 属性和 继承 属性。自身 属性是直接在实例上定义的,而 继承 属性则来自 prototype 对象。
当使用 属性访问器 时,JavaScript 会先在对象的 自身属性列表 中查找。如果没有找到该属性,它会在对象的 原型链 中查找。

在你的例子中,wrapper() 方法在对象实例上定义了一个自身属性 doABC,这是一个会弹出 'in wrapper' 的函数。即使对象有一个原型,其中也有一个相同的属性 doAbc 会弹出 'in Model',JavaScript 仍然会使用自身属性。

function wrapper(target) {
    // Define an own property "doABC"
    target.doABC = function () {
        alert('in wrapper');
    };
    return target;
}

function Model() {
    wrapper(this);
}

// Define an inherited property "doABC"
Model.prototype.doABC = function () {
    alert('in Model');
};

var a = new Model();

//Use the own property "doABC". The inherited "doABC" is ignored.
a.doABC(); 

作为补充,可以使用 delete 运算符删除自身属性。删除后,对象将使用继承的属性。

// delete the own property "doABC"
delete a['doABC'];

// the inherited "doABC" will be used. Alerts "in Model"
a.doABC();

查看完整的演示示例。

答案#2

让我看看我是否能解释一下:

你这里有两个独立版本的doABC。

你的 target.doABC 为你的 Model 的 该 实例创建一个特定的函数,每个 Model 都有自己的 doABC。

因为 Model 有一个 doABC,所以 JavaScript 引擎不需要向“链上”查找其他东西,因此它永远不会去查找 Model.prototype.doABC 版本。

你可以通过添加这些行来看到这一点:

Model.prototype.doXYZ = function () {
    alert('in Model');
};

并呼叫

a.doXYZ();

由于 a 没有自己的 doXYZ,只有在这种情况下,它才会向上查找链,并在原型中看到该方法。