更改对象__proto__属性的正确方法

The correct way to change object __proto__ property

本文关键字:方法 proto 对象 属性      更新时间:2023-09-26

我非常了解javascript原型继承,但我有一个类似于角度scopes的情况,我不知道如何处理它。

让我们从错误开始(因为更改__proto__属性是个坏主意(但工作示例

https://jsfiddle.net/hxm61r7j/

function Scope() {
}
Scope.prototype.$new = function() {
    var new_scope = new Scope();
    //TODO: change line bellow 
    new_scope.__proto__ = this;
    return new_scope;
}
// Create root scope
var scope_level_1 = new Scope();
scope_level_1.a = 'scope_level_1 a';
scope_level_1.b = 'scope_level_1 b';
// Create scope which inherits from parent
var scope_level_2 = scope_level_1.$new();
scope_level_2.b = 'scope_level_2 b';
// We don't have property "a" in "scope_level_2" so it will be taken from "scope_level_1"
// But we have property "b" in "scope_level_2" so it will be taken from there
console.log(scope_level_2.a, scope_level_2.b);

如您所见,我需要一种方法来创建某种具有一些属性的scope。稍后我需要创建其他scope它将继承前一个。我的意思是,如果未在当前范围内定义属性,它将从父级中获取。

但是我不知道如何更改此行:new_scope.__proto__ = this;

我想你正在寻找Object.create().

此函数允许您创建一个新的 JavaScript 对象,并将内部原型属性 ( __proto__ ( 设置为作为第一个参数传递给函数的任何对象:

Scope.prototype.$new = function() {
    var new_scope = Object.create(this);
    // If you also need to call the constructor function:
    Scope.call(new_scope);
    return new_scope;
}

或者,您可以使用 Object.setPrototypeOf() ,但这是 ECMAScript 6 的一部分,浏览器支持可能会有所不同:

Scope.prototype.$new = function() {
    var new_scope = new Scope();
    Object.setPrototypeOf(new_scope, this);
    return new_scope;
}

请注意,__proto__属性仅在 ES 6 中进行了标准化,因此不鼓励直接操作。

首先,

使用 dunder proto 不是一个好的做法,有 setPrototyOf 用于该原因

设置原型

当然,除非您需要支持较旧的IE版本。

现在请记住,在设置原型后,您还需要再次设置构造函数。所以正确的是new_scope。原型 = 这个原型;new_scope。proto.constructor=this.prototype.constructor