博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于javascript的new做些什么(待翻译)
阅读量:6636 次
发布时间:2019-06-25

本文共 9242 字,大约阅读时间需要 30 分钟。

  hot3.png

http://joost.zeekat.nl/constructors-considered-mildly-confusing.html

Constructors considered mildly confusing

 ]

Consider this quote from , page 111 that came up in last month:

In javascript, every object has a constructor property that refers to the constructor function that initializes the object.

Sounds nice: it makes constructors sound static like classes in Java. Even the new Constructor()syntax looks like it. And it seems true:

function MyConstructor() {} var myobject = new MyConstructor(); myobject.constructor == MyConstructor;     // true
Run this code ==>

But life isn't that simple:

function MyConstructor() {} MyConstructor.prototype = {}; var myobject = new MyConstructor();  myobject.constructor == MyConstructor;  // false
Run this code ==>

What's going on? Some definitions

Objects and methods

Javascript  objects are simply bags of named properties that you can read and set. Javascript does not have classes. 

Functions in javascript are first-class objects. Methods in javascript are just properties that are functions.

Prototypes

The prototype of an object is an internal property that I'll refer to here as "[[Prototype]]" (as in). In other words, obj.prototype is in general not the obj's [[Prototype]]. The standard does not provide any way to retrieve the [[Prototype]] property from an object.

Javascript objects can delegate properties to their [[Prototype]] (and their [[Prototype]] can do the same; all the way up to Object.prototype).

Property lookup

Whenever a property "propname" of an object is read, the system checks if that object has a property named "propname". If that propery does not exist, the system checks the object's [[Prototype]] for that property, recursively.

This means that objects that share a [[Protoype]] also share the properties of that [[Prototype]].

Whenever a property "propname" of an object is set, the property is inserted into that object, ignoring the [[Prototype]] chain of that object.

The "[[Prototype]]" property is set from the (public) "prototype" property of the constructor function when constructor function is called.

What's going on? Line by line.

This is what the relevant prototype and [[Prototype]] properties look like. The ellipses are objects, the arrows are properties that reference other objects. The [[Prototype]] chain(s) are in green.

#1: function MyConstructor() {}

14013935_3JqG.png

Fairly simple. MyConstructor.prototype is a property that's automatically created which in turn has aconstructor property pointing back at MyConstructor. Remember that: the only objects that in fact have a constructor property by default are the automatically created prototype properties of functions.

The rest isn't really relevant but may confuse and enlighten (and hopefully in that order):

MyConstructor's [[Prototype]] is Function.prototype, not MyConstructor.prototype. Also note that the[[Prototype]] chain for each object ends up at Object.prototype.

Object.prototype's [[Prototype]] is actually null indicating that it's the end of the chain. 

For the next steps I'm leaving out the [[Prototype]] chain of MyConstructor for clarity, since it doesn't change and it's not relevant.

#2: MyConstructor.prototype = {}

14013937_0Sql.png

We've now done away with the predefined MyConstructor.protoype object and replaced it with an anonymous object, shown here as "{}". This object does not have a constructor property,

#3: var myobject = new MyConstructor();

14013938_SH62.png

From this graph, following the  rules, we can now see that myobject.constructor is delegated to Object.prototype.constructor, which points to Object. In other words:

function MyConstructor() {} MyConstructor.prototype = {}; var myobject = new MyConstructor();  myobject.constructor == Object
Run this code ==>

What about instanceof ?

Javascript provides the instanceof operator that's intended to check the prototype chain of the object you're dealing with. From the above you might think that the following would return false:

function MyConstructor() {} MyConstructor.prototype = {}; var myobject = new MyConstructor();  myobject instanceof MyConstructor  // true
Run this code ==>

But in fact it works (click the button). It also notices that myobject delegates to Object.prototype:

function MyConstructor() {} MyConstructor.prototype = {}; var myobject = new MyConstructor();  myobject instanceof Object
Run this code ==>

When instanceof is called it checks the prototype property of the given constructor and checks it agains the [[Prototype]] chain of the given object. In other words, it's not dependent on theconstructor property.

All nice and dandy, but you can still break it if you try hard enough:

function MyConstructor() {} var myobject = new MyConstructor(); MyConstructor.prototype = {};  [ myobject instanceof MyConstructor,     // false !   myobject.constructor == MyConstructor, // true !   myobject instanceof Object ]           // true
Run this code ==>

This is what the prototype chains look like after running that:

14013939_7FOm.png

Constructors are not classes

In a class-based object system, typically classes inherit from each other, and objects are instances of those classes. Methods and properties that are shared between instances are (at least conceptually) properties of a class. Properties (and for some languages, methods) that should not be shared are properties of the objects themselves.

Javascript's constructors do nothing like this: in fact constructors have their own [[Prototype]]chain completely separate from the [[Prototype]] chain of objects they initialize.

Constructors do not work like class-based initializers

A constructor call associates a new object with a [[Prototype]] the constructor function may set additional properties on the object. Constructor calls do not call "inherited" constructors, and they shouldn't because the object's [[Prototype]] (the constructor's prototype) is assumed to be shared and (probably) already initialized.

Constructors are just functions

Any user-defined function in javascript automatically gets a prototype property which in turn has aconstructor property that refers back to the function.

Any user-defined function in javascript can be called as a constructor by prepending new to the call. This will pass a new this object to the function and its [[Prototype]] property will be set to the prototype property of the function.

Comments

If you want, you can leave your comments , or catch my attention in comp.lang.javascript.

Foot notes

0]

"Javascript" in this text refers to implementations of .

1]

The specification mentions that every object must have an internal [[Class]] property. The values of these properties are strings and "used internally to distinguish different kinds of built-in objects". Javascript code can't establish new values for the [[Class]] property, but the host system can.

Anyone not implementing or embedding a javascript interpreter is probably best off ignoring this property, since it's (almost) invisible and there are better ways to distinguishing build-in types in the language if you need to.

Still curious? See section 8.6.2 of .

2]

John G Harris wrote in on comp.lang.javascript to say that this isn't quite true, and he's technically correct. The best kind of correct :-) Theoretically, the host system may swap theObject.prototype property with something else. As far as Javascript code is concerned, Object.prototypeshould be read-only. In the only browser I've tested (firefox) you can assign a new value toObject.prototype, but the assignment is ignored.

In any case, if you or the host system change it in a fit of perversity it will not have affect the respective [[Prototype]] properties of any object, not even those created later.

In other words, wherever you read Object.prototype in this text, it refers to what the specs call "The initial value of Object.prototype".

The same caveat applies to Function.prototype, Array.prototype, String.prototype, Boolean.prototype,Number.prototype, Date.prototype, RegExp.prototype and Error.prototype. Search the specs for "initial value" and you'll find them (and some more interesting stuff, too).

Example:

// running this code has a very slight chance of breaking the examples // on this page. So you may want to reload after trying it, if the results // don't match the expectations. (Oh, and let me know!)  var oldp = Object.prototype; Object.prototype = {}; var b = new Object(); [ b.constructor == Object,                      // should be true   b.constructor.prototype == Object.prototype,  // should be true   Object.prototype == oldp ]                    // should be true
Run this code ==>

References

A comp.lang.javascript question

Subject: "x.constructor == Foo" vs "x instanceof Foo". Message-ID: <fniu6a$2cn$1@reader2.panix.com>

Ecma-262

Standard ECMA-262. ECMAScript Language Specification 3rd edition (December 1999) 

Flanagan 2006

JavaScript: The Definitive Guide, Fifth Edition. ISBN 10: 0-596-10199-6 | ISBN 13:9780596101992

Changes

2008/02/11 - initial version

2008/02/13 - added footnote  and modified footnote  to be even less normative (also, removed[[Class]] "Class")

2008/02/17 - rewrote note  once again. And corrected it. Added .

Author & copyright

(c)2008 Joost Diepenmaat, Zeekat Softwareontwikkeling.

URI: 

 ]

转载于:https://my.oschina.net/caiwf/blog/113595

你可能感兴趣的文章
NSAssert和NSLog
查看>>
Linux系统中常用操作命令
查看>>
ARTS打卡计划第6周-TIPS-多台服务器免密码登录
查看>>
西安Uber优步司机奖励政策(12月14日到12月20日)
查看>>
iOS开发学习笔记 2-5 C语言部分 数组
查看>>
php,redis,centos5安装完全记录
查看>>
×××应用之GRE
查看>>
无效的过程调用或参数: 'Instr'解决方法
查看>>
python笔记第十天 模块
查看>>
编程实现栈的入栈/出栈操作
查看>>
假期总结四
查看>>
[NOI 2018] 归程
查看>>
[CF845G]Shortest Path Problem?
查看>>
Ubuntu 使用163镜像(12.10)
查看>>
SSM框架中使用文件上传的示例
查看>>
js_高级_函数进阶
查看>>
c++二分法
查看>>
java中小工具————UUID
查看>>
JVM备忘点(1.8以前)
查看>>
iOS开发小技巧--利用运行时得到隐藏的成员变量
查看>>