与其他数据类型一样, 对象从内置的 Object 原型继承属性和方法, 这意味着生成的对象同时包含您定义的属性和 proto 属性,其中包含从原型继承的方法:
let myObject = { 'booleanValue' : true }; myObject; > Object { booleanValue: true } booleanValue: true [[prototype]]: Object { … } __defineGetter__: function __defineGetter__() __defineSetter__: function __defineSetter__() __lookupGetter__: function __lookupGetter__() __lookupSetter__: function __lookupSetter__() __proto__: … constructor: function Object() hasOwnProperty: function hasOwnProperty() isPrototypeOf: function isPrototypeOf() propertyIsEnumerable: function propertyIsEnumerable() toLocaleString: function toLocaleString() toString: function toString() valueOf: function valueOf() <get __proto__()>: function __proto__() <set __proto__()>: function __proto__() 原型属性不应直接通过属性键进行访问。如 在上一个示例中,[[prototype]] 暗示了这一点 或以 <prototype> 表示法表示和来源 关于原型的属性键的文档:
// Chrome: let emptyObject = {}; emptyObject; > {} [[prototype]]: Object // Firefox: let emptyObject = {}; emptyObject; > Object { } <prototype>: Object { … } 虽然所有常用浏览器都使用 __proto__ 作为事实上的标准,但这并不是 已正式标准化,应避免使用正式版代码。
let emptyObject = {}; emptyObject.__proto__; > Object { … } __defineGetter__: function __defineGetter__() __defineSetter__: function __defineSetter__() __lookupGetter__: function __lookupGetter__() __lookupSetter__: function __lookupSetter__() __proto__: constructor: function Object() hasOwnProperty: function hasOwnProperty() isPrototypeOf: function isPrototypeOf() propertyIsEnumerable: function propertyIsEnumerable() toLocaleString: function toLocaleString() toString: function toString() valueOf: function valueOf() <get __proto__()>: function __proto__() <set __proto__()>: function __proto__() 相反,您可以直接访问和修改对象的 [[Prototype]], 使用内置的 Object.getPrototypeOf() 和 Object.setPrototypeOf() 方法:
let myObj = { "value" : 5 }; let protoParent = { "protoValue" : true }; myObj; Object { value: 5 } value: 5 <prototype>: Object { … } Object.getPrototypeOf( myObj ); > Object { … } __defineGetter__: function __defineGetter__() __defineSetter__: function __defineSetter__() __lookupGetter__: function __lookupGetter__() __lookupSetter__: function __lookupSetter__() __proto__: constructor: function Object() hasOwnProperty: function hasOwnProperty() isPrototypeOf: function isPrototypeOf() propertyIsEnumerable: function propertyIsEnumerable() toLocaleString: function toLocaleString() toString: function toString() valueOf: function valueOf() <get __proto__()>: function __proto__() <set __proto__()>: function __proto__() Object.setPrototypeOf( myObj, protoParent ); > Object { value: 5 } value: 5 <prototype>: Object { protoValue: true } 为了区分继承的属性和作者定义的属性, 后者通常称为对象“自己的属性”。
如果指定属性,则内置 Object.hasOwn() 方法会返回 true 是对象的直接属性,如果该属性false是继承的或 不存在。请尽可能使用 Object.hasOwn() 而不是继承的 hasOwnProperty() 方法,该方法不支持 Object.create()。
let myObject = { 'myValue' : 100 }; Object.hasOwn( myObject, 'myValue' ); > true myObject.__proto__; // The Object prototype inherited by `myObject` is present: > Object { … } Object.hasOwn( myObject, '__proto__' ); // The Object prototype inherited by `myObject` is not an "own property:" > false 检查您的理解情况
为什么应避免使用 __proto__?
它不是标准化的。
很多浏览器都不支持此功能。
这会让日后的代码维护者感到困惑。