Prototype Methods, Objects Witho

JavaScript Prototype Methods, Objects Without proto (JavaScript原型方法,不带__ proto __的对象)

Let’s first explore the modern methods for setting up a prototype. (让我们首先探索设置原型的现代方法。)

Amongst them are:

Object.create(proto[, descriptors]). This method is used for creating an empty object with given proto as [[Prototype]], as well as, optional property descriptors. Object.getPrototypeOf(obj). This one helps to return the [Prototype]] of the obj. Object.setPrototypeOf(obj, proto). The method is aimed at setting the [[Prototype]] of the obj to proto. (Object.create (proto [, descriptors])。 此方法用于使用给定的proto作为[[Prototype]]以及可选属性描述符创建空对象。 Object.getPrototypeOf (obj)。这有助于返回对象的[Prototype]]。 Object.setPrototypeOf (obj, proto)。 该方法旨在将obj的[[Prototype]]设置为proto。)

So, you can use the mentioned methods instead of the proto. (因此,您可以使用上述方法代替__ proto __。)

Take a look at the following example:

let animal = {
 speaks: true
};
let dog = Object.create(animal);// create a new object with animal as a prototype
console.log(dog.speaks); // true
console.log(Object.getPrototypeOf(dog) === animal); // true
Object.setPrototypeOf(dog, {}); // change the prototype of  dog to {}

There is an alternative argument for Object.create: property descriptors. You have the option of providing additional properties to the object there.

For example:

let animal = {
 speaks: true
};
let dog = Object.create(animal, {
 runs: {
   value: true
 }
});
console.log(dog.runs); // true

For performing an object cloning, it’s more convenient to use Object.create than copying properties in for..in. (对于执行对象克隆,使用Object.create比在for.. in中复制属性更方便。)

The example looks like this:

// fully identical shallow clone of obj
let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));

The call mentioned above creates the exact copy of obj, which includes all the properties: non-enumerable and enumerable, data properties, setters/getters, and with the suitable [[Prototype]].

Short History

Short History (简短历史)

There are many ways of managing the [[Prototype]]. (管理[[Prototype]]的方法有很多。)

One of the reasons is that the “prototype” property has worked since ancient times. In 2012, Object.create was added to the standard. It started to allow creating objects with proto accessor. (其中一个原因是“原型”属性自古以来就一直在工作。2012年, Object.create被添加到标准中。它开始允许使用__ proto __访问器创建对象。)

Later, in 2015, Object.setPrototypeOf and Object.getPrototypeOf appeared in the standard for performing the same functionality as proto. (后来,在2015年, Object.setPrototypeOf和Object.getPrototypeOf出现在标准中,用于执行与__ proto __相同的功能。)

Nowadays, all these methods are at the developers’ disposal. (如今,所有这些方法都可以由开发人员使用。)

Technically, it is possible to get/set [[Prototype]] at any time. But, commonly, it is set once while creating the object and is not modified anymore. Changing a prototype with Object.setPrototypeOf or obj.proto= can be considered a slow operation. The reason is that it breaks internal optimizations for object property access operations. (从技术上讲,可以随时获取/设置[[Prototype]]。但是,通常在创建对象时设置一次,不再修改。使用Object.setPrototypeOf或obj.proto =更改原型可以被认为是一个缓慢的操作。原因是它破坏了对象属性访问操作的内部优化。)

“Very Plain” Objects

“Very Plain” Objects (“非常简单”的对象)

You can use objects as associative arrays for storing key/value pairs. But in the event of trying to store user-provided keys inside it, a unique error may occur: all the keys will work well except “proto”.

Look at this example:

let obj = {};
let key = prompt("What is the key value?", "__proto__");
obj[key] = "some value";
console.log(obj[key]); // [object Object], not "some value"!

Here when the user types proto, the assignment is ignored.
Thus, the proto property is unique. It can be either null or an object. A string can’t transform into a prototype. (这里,当用户键入__ proto __时,分配将被忽略。
因此, __ proto __属性是唯一的。 它可以是null或对象。 字符串无法转换为原型。)

So, the main problem is that “proto” is not saved accurately. It’s a bug. Some unexpected things can happen while assigning toString that is a function by default. (因此,主要问题是“__ proto __”没有准确保存。 这是一个错误。 在分配默认情况下为函数的toString时,可能会发生一些意外情况。)

To avoid such kinds of problems, first, you can switch to using Map . (为了避免此类问题,首先,您可以切换到使用地图。)

The Object may also be helpful. The proto is not an object property, but an accessor property of Object.prototype. (该对象也可能有帮助。__ proto __不是对象属性,而是Object.prototype的访问器属性。)

Check out this case:

In obj.proto is set or read, the appropriate setter/getter is called from its prototype, as well as, sets/gets [[Prototype]]. (在obj.__proto__中设置或读取,从其原型调用适当的setter/getter ,以及set/gets [[Prototype]]。)

If you intend to use an object as an associative array, you can implement it with a trick. (如果您打算将对象用作关联数组,则可以使用技巧来实现它。)

Here is how to do it:

let obj = Object.create(null);
let key = prompt("What's the key value?", "__proto__");
obj[key] = "some value";
console.log(obj[key]); // "some value"

Object.create(null) generates an empty object without a prototype:

It can be assumed that there isn’t any inherited getter/setter for proto. It is handled as an ordinary data property. (可以假设__ proto __没有任何继承的getter/setter。它作为普通数据属性处理。)

Such objects can be named “very plain” because they are more straightforward than the ordinary plain object {…}.

The disadvantage is that such objects lack built-in object methods (toString). (缺点是此类对象缺乏内置对象方法( toString )。)

For instance:

let obj = Object.create(null);
console.log(obj); // Error (no toString)

Usually, it’s fine for associative arrays. (通常,它适用于关联数组。)



请遵守《互联网环境法规》文明发言,欢迎讨论问题
扫码反馈

扫一扫,反馈当前页面

咨询反馈
扫码关注
返回顶部