Crockford 的对象创建技术发生了什么?

发布于 2024-08-31 10:16:33 字数 984 浏览 6 评论 0原文

只有 3 行代码,但我无法完全理解这一点:(

Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
};
newObject = Object.create(oldObject);

来自 原型继承)

  1. Object.create() 首先创建一个名为 F 的空函数。我认为函数是一种对象。这个 F 对象存储在哪里?我猜是全局性的。

  2. 接下来我们的oldObject,作为o传入,成为函数F的原型。函数(即对象)F 现在从我们的 oldObject 中“继承”,从某种意义上说,名称解析将通过它进行路由。很好,但我很好奇对象的默认原型是什么,Object?对于函数对象来说也是如此吗?

  3. 最后,F被实例化并返回,成为我们的newObject。这里的 new 操作是绝对必要的吗? F 不是已经提供了我们需要的东西,还是函数对象和非函数对象之间存在关键区别?显然,使用这种技术不可能有一个构造函数。

下次调用 Object.create() 时会发生什么?全局函数F是否被覆盖?当然它不会被重用,因为这会改变以前配置的对象。如果多个线程调用 Object.create() 会发生什么,是否有任何类型的同步来防止 F 上的竞争条件?

There are only 3 lines of code, and yet I'm having trouble fully grasping this:

Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
};
newObject = Object.create(oldObject);

(from Prototypal Inheritance)

  1. Object.create() starts out by creating an empty function called F. I'm thinking that a function is a kind of object. Where is this F object being stored? Globally I guess.

  2. Next our oldObject, passed in as o, becomes the prototype of function F. Function (i.e., object) F now "inherits" from our oldObject, in the sense that name resolution will route through it. Good, but I'm curious what the default prototype is for an object, Object? Is that also true for a function-object?

  3. Finally, F is instantiated and returned, becoming our newObject. Is the new operation strictly necessary here? Doesn't F already provide what we need, or is there a critical difference between function-objects and non-function-objects? Clearly it won't be possible to have a constructor function using this technique.

What happens the next time Object.create() is called? Is global function F overwritten? Surely it is not reused, because that would alter previously configured objects. And what happens if multiple threads call Object.create(), is there any sort of synchronization to prevent race conditions on F?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

何必那么矫情 2024-09-07 10:16:34

1) Object.create() 开始于
创建一个名为 F 的空函数。
我认为函数是一种
的对象。这个F对象在哪里
被存储?我想在全球范围内。

不,它存储在 Object.create 函数的本地范围内,每次调用 Object.create 时,都会重新创建此函数 F

您甚至可以通过将 F 存储在闭包上并重用它来创建内存效率更高的实现:

if (typeof Object.create !== "function") {
  Object.create = (function () {
    function F() {} // created only once
    return function (o) {
      F.prototype = o; // reused on each invocation
      return new F();
    };
  })();
}

2) 接下来是我们的 oldObject,以 o 的形式传入,
成为函数F的原型。
函数(即对象)F now
从我们的 oldObject 中“继承”
感知名称解析将路由
通过它。很好,但我很好奇什么
默认原型是
对象,对象?这也适用于
函数对象?

所有对象都有一个构建原型链的内部属性,该属性称为 [[Prototype]],它是一个内部属性,尽管有些实现允许您访问它,例如 mozilla,使用 < code>obj.__proto__ 属性。

创建新对象时,即var obj = {};,默认的[[Prototype]]Object.prototype

所有函数都有一个 prototype 属性,当函数用作 构造函数,使用new 运算符调用。

它在幕后创建一个新的对象实例,并将该对象 [[Prototype]] 设置为其构造函数的 prototype 属性。

3) 最后,F 被实例化并且
返回,成为我们的 newObject。是
“新”操作绝对必要
这里? F不是已经提供了什么吗
我们需要,或者有一个关键的
函数对象之间的区别
和非函数对象?显然它
将不可能有
使用 this 的构造函数
技术。

是的,new 运算符在此方法中至关重要。

new 操作符是设置对象的[[Prototype]]内部属性的唯一标准方法,如果你好奇它是如何工作的,你可以看一下到 [[Construct]] 内部运作。

下次会发生什么
Object.create() 被调用了吗?是全球性的
函数F被覆盖?肯定是
不重复使用,因为这会改变
先前配置的对象。和
如果多个线程调用会发生什么
Object.create(),是否有任何类型的
同步以防止竞争
F 的条件?

下次调用 Object.create 时,仅在方法调用的范围内实例化新的本地 F 函数,您不必担心竞争条件

请注意,此实现几乎不符合 ECMAScript 第五版规范,在该方法中,您可以传递一个属性描述符来初始化对象。

所有浏览器供应商都在实现它(已经在 Firefox 3.7 alpha、最新的 Wekit Nightly Builds 和 Chrome 5 Beta 上可用),所以我建议您至少在覆盖它之前检查是否存在本机实现。

1) Object.create() starts out by
creating an empty function called F.
I'm thinking that a function is a kind
of object. Where is this F object
being stored? Globally I guess.

No, it's stored on the local scope of the Object.create function, each time you invoke Object.create this function F will be recreated.

You could even create a more memory-efficient implementation, by storing F on a closure, and reuse it:

if (typeof Object.create !== "function") {
  Object.create = (function () {
    function F() {} // created only once
    return function (o) {
      F.prototype = o; // reused on each invocation
      return new F();
    };
  })();
}

2) Next our oldObject, passed in as o,
becomes the prototype of function F.
Function (i.e., object) F now
"inherits" from our oldObject, in the
sense that name resolution will route
through it. Good, but I'm curious what
the default prototype is for an
object, Object? Is that also true for
a function-object?

All objects have an internal property that builds the prototype chain, this property is known as [[Prototype]], it's an internal property, although some implementations let you access to it, like mozilla, with the obj.__proto__ property.

The default [[Prototype]] when you create a new object, i.e. var obj = {}; is Object.prototype.

All functions have a prototype property, this property is used when a function is used as a Constructor, invoked with the new operator.

A new object instance it's created behind the scenes, and this object [[Prototype]] is set to its Constructor's prototype property.

3) Finally, F is instantiated and
returned, becoming our newObject. Is
the "new" operation strictly necessary
here? Doesn't F already provide what
we need, or is there a critical
difference between function-objects
and non-function-objects? Clearly it
won't be possible to have a
constructor function using this
technique.

Yes, the new operator is essential in this method.

The new operator is the only standard way to set the [[Prototype]] internal property of an object, if you are curious about how it works, you can give a look to the [[Construct]] internal operation.

What happens the next time
Object.create() is called? Is global
function F overwritten? Surely it is
not reused, because that would alter
previously configured objects. And
what happens if multiple threads call
Object.create(), is there any sort of
synchronization to prevent race
conditions on F?

The next time Object.create is invoked, a new local F function is instantiated only within the scope of the method call, you shouldn't worry about race conditions.

Note that this implementation hardly conforms the Object.create described in the ECMAScript 5th Edition Specification, in that method, you could pass a property descriptor to initialize the object.

All browser vendors are implementing it (already available on Firefox 3.7 alphas, latest Wekit Nightly Builds and Chrome 5 Beta), so I would recommend you at least to check if a native implementation exist before overriding it.

琴流音 2024-09-07 10:16:34

1)函数确实是一种对象。每次调用 Object.create 时都会创建一个带有标识符 F 的函数对象,并且只能在执行 Object.create 时使用该标识符进行访问>。因此,每次调用Object.create时,您都会得到一个不同的函数对象F。该函数对象作为 Object.create 返回的对象的 constructor 属性存在。

2)

F 现在“继承”了我们的 oldObject,
从某种意义上说,名称解析将
穿过它的路线

这并不正确。将对象 someObject 分配给函数的 prototype 属性仅意味着通过调用此函数作为构造函数创建的任何未来对象的原型将是 someObject.

3) new 对于这项技术来说绝对至关重要。只有通过将函数作为构造函数调用,它才会生成一个新对象,并且该对象的原型(通常不可访问)被设置为构造函数的 prototype 属性。没有其他(标准化)方法来设置对象的原型。

最后,浏览器中的 JavaScript 是单线程的,因此不可能出现您所描述的竞争条件。

1) A function is indeed a kind of object. A function object with identifier F is created each time Object.create is called, and is only accessible with that identifier within that execution of Object.create. Therefore, each time Object.create is called, you get a different function object F. This function object lives on as the constructor property of the object returned by Object.create.

2)

F now "inherits" from our oldObject,
in the sense that name resolution will
route through it

This isn't really correct. Assigning an object someObject to the prototype property of a function just means that the prototype of any future object created by calling this function as a constructor will be someObject.

3) The new is absolutely vital to this technique. Only by calling a function as a constructor does it produce a new object, and that object's prototype (which is not generally accessible) is set to the constructor function's prototype property. There is no other (standardised) way to set an object's prototype.

Finally, JavaScript in browsers is single threaded, so race conditions such as you describe are not possible.

夜空下最亮的亮点 2024-09-07 10:16:34

您在这里的主要误解是 F 具有全球范围。它是在 Object.create 的主体中声明的,因此仅在该方法块的范围内。

Your major misunderstanding here is that F has global scope. It is declared in the body of Object.create and consequently is only in scope within that method block.

活雷疯 2024-09-07 10:16:34

>显然,使用这种技术不可能有一个构造函数。

该技术已经是一个对象构造函数,因为它返回 new F(),但不能像 new man('John','Smith') 那样设置属性值。但是,如果修改 Object.create 代码,则可以进行实例化。例如下面的 sarah 对象可以使用 Object.creator 构造和实例化,并将继承 getName 方法。

var girl = {
   name: '',
   traits: {},
   getName: function(){return this.name}
}

var sarah = Object.creator(girl, 'Sarah', {age:29,weight:90})

sarah 对象将由自己的属性 { name:'Sarah', Traits:{age:9,weight:49} } 组成,并且继承 sarah.getName() 的原型将生成 'Sarah'。

以下方法依赖于按创建顺序使用“for(prop in o)”枚举的自己的属性。尽管 ECMA 规范没有保证,但这个示例(以及一些更复杂的示例)适用于所有经过测试的主要浏览器 (4),前提是使用了 hasOwnProperty(),否则则不然。

Object.creator = function(o) {
   var makeArgs = arguments 
   function F() {
      var prop, i=1, arg, val
      for(prop in o) {
         if(!o.hasOwnProperty(prop)) continue
         val = o[prop]
         arg = makeArgs[i++]
         if(typeof arg === 'undefined') break
         this[prop] = arg
      }
   }
   F.prototype = o
   return new F()
}

官方的ECMA Object.create有一个可选的第二个参数propertiesObject,它可以实例化属性值,但它是一个对象而不是通常的列表,并且使用起来看起来很尴尬。例如,我相信:-

o2 = Object.create({}, { p: { value: 42, writable: true, enumerable: true, configurable: true } });

相当于更简单的旧方法:-

o2 = new function(p) { this.p=p }(42)

o2 = Object.creator({p:''}, 42)

> Clearly it won't be possible to have a constructor function using this technique.

The technique is already an object constructor since it returns new F(), but no property values can be set as for say new man('John','Smith'). However, if the Object.create code is modified, instantiation is possible. For example the sarah object below can be constructed and instantiated using Object.creator, and will inherit the getName method.

var girl = {
   name: '',
   traits: {},
   getName: function(){return this.name}
}

var sarah = Object.creator(girl, 'Sarah', {age:29,weight:90})

The sarah object will then consist of own properties { name:'Sarah', traits:{age:9,weight:49} }, and the prototype inherited sarah.getName() will produce 'Sarah'.

The following method relies on own properties enumerating with 'for(prop in o)' in creation order. Although not guaranteed by ECMA specs, this example (and a few more complex) worked for all major browsers (4) tested, providied hasOwnProperty() was used, otherwise not.

Object.creator = function(o) {
   var makeArgs = arguments 
   function F() {
      var prop, i=1, arg, val
      for(prop in o) {
         if(!o.hasOwnProperty(prop)) continue
         val = o[prop]
         arg = makeArgs[i++]
         if(typeof arg === 'undefined') break
         this[prop] = arg
      }
   }
   F.prototype = o
   return new F()
}

The official ECMA Object.create has an optional 2nd parameter, propertiesObject, that can instantiate property values, but it is an object rather than the usual list, and looks awkward to use. E.g. I believe:-

o2 = Object.create({}, { p: { value: 42, writable: true, enumerable: true, configurable: true } });

is equivalent to the much simpler old way:-

o2 = new function(p) { this.p=p }(42)

and

o2 = Object.creator({p:''}, 42)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文