论坛首页 Web前端技术论坛

JavaScript 对象性的构造分析 - 从现象到本质

浏览 25317 次
该帖已经被评为精华帖
作者 正文
   发表时间:2008-06-23  
笨笨狗 写道
楼上的这种写法是有必要的,在某些情况下来说,呵呵。推荐看看周爱民的《javascript语言精粹与编程实践》,里面有讲

嘿嘿 有错字

《javascript语言精与编程实践》
0 请登录后投票
   发表时间:2008-06-24  
好吧,我承认这里我偷懒了,的确我是过于注重推理的过程而忽略了给出一个权威而有说服的证据,我只是想从表面现象推断出一些东西。
那让我们看看“上帝“是怎么说的。。
我在网上下了Ecma的specification,Ecma-262,参考如下链接:
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf

用PDF Reader 打开时, Page的页码并不对,为了方便起见,我这里的Page 为左边Navigator的页码数

前提:
Page 85:
NOTE:
A prototype property is automatically created for every function, to allow for the possibility that the function will be used as a constructor.

这段说明证实了我在文中所提到的假设:
当一个变量以 "function" 定义时,property "prototype" 会自动的创建,当一个变量具有"prototype"时,才能做为一个constructor,这点我在文章的开头已经提出。

文中提到了直接 call Function(Function()), 2者事实上是相等的
Page 97, 15.3 Function Objects:
15.3.1 The Function Constructor Called as a Function
When Function is called as a function rather than as a constructor, it creates and initialises a new Function object. Thus the function call Function(…) is equivalent to the object creation expression new Function(…) with the same arguments.

而且在Ecma Specification 中, 紧接着他又对 直接 "call" Function 作出了解释:
15.3.1.1 Function (p1, p2, … , pn, body)
When the Function function is called with some arguments p1, p2, … , pn, body (where n might be 0, that is, there are no “p” arguments, and where body might also not be provided), the following steps
are taken:
1. Create and return a new Function object as if the function constructor had been called with the same arguments (15.3.2.1).

在直接"call"的时候,事实上也是返回一个 "new Function object", 就好像把Function当作一个constructor "call"一样(new Function()),接下去的处理步骤和15.3.2.1一样,我们看一下15.3.2 节
15.3.2 The Function Constructor
When Function is called as part of a new expression, it is a constructor: it initialises the newly created object.
15.3.2.1 new Function (p1, p2, … , pn, body)
The last argument specifies the body (executable code) of a function; any preceding arguments
specify formal parameters.
When the Function constructor is called with some arguments p1, p2, … , pn, body (where n might
be 0, that is, there are no “p” arguments, and where body might also not be provided), the following
steps are taken:
1. Let P be the empty string.
2. If no arguments were given, let body be the empty string and go to step 13.
3. If one argument was given, let body be that argument and go to step 13.
4. Let Result(4) be the first argument.
5. Let P be ToString(Result(4)).
6. Let k be 2.
7. If k equals the number of arguments, let body be the k’th argument and go to step 13.
8. Let Result(8) be the k’th argument.
9. Call ToString(Result(8)).
10. Let P be the result of concatenating the previous value of P, the string "," (a comma), and
Result(9).
11. Increase k by 1.
12. Go to step 7.
13. Call ToString(body).
14. If P is not parsable as a FormalParameterListopt then throw a SyntaxError exception.
15. If body is not parsable as FunctionBody then throw a SyntaxError exception.
16. Create a new Function object as specified in 13.2 with parameters specified by parsing P as a
FormalParameterListopt and body specified by parsing body as a FunctionBody. Pass in a scope
chain consisting of the global object as the Scope parameter.
17. Return Result(16).


我们发现2者确实是等价的
至于返回的变量为什么return function(){
}和return Object 会产生不同的"this"呢,
我目前还没有在文中找到直接的证据,但是从
Page 100, 15.3.5.3
15.3.5.3 [[HasInstance]] (V)
Assume F is a Function object.
When the [[HasInstance]] method of F is called with value V, the following steps are taken:
1. If V is not an object, return false.
2. Call the [[Get]] method of F with property name "prototype".
3. Let O be Result(2).
4. If O is not an object, throw a TypeError exception.
5. Let V be the value of the [[Prototype]] property of V.
6. If V is null, return false.
7. If O and V refer to the same object or if they refer to objects joined to each other (13.1.2), return
true.
8. Go to step 5.

和F的执行结果不无关系.
0 请登录后投票
   发表时间:2008-06-24  
我抽空会研究ECMA的文档的,希望能给出权威的证据论证我的测试结果
希望大家多多挑毛病
0 请登录后投票
   发表时间:2008-06-24  
我给出
var f = new F();
和f = F();
2者是等价的这个结论,是基于我做了大量的测试的基础上,至于为什么得到这个结果我当时也很迷惑
还好,在ECMA的文档中找到了证据,大家可以研究下文档中的概念,结合我的测试结果,不难理解JS整个对象机制
0 请登录后投票
   发表时间:2008-06-24  
alucardggg 写道
我给出
var f = new F();
和f = F();
2者是等价的这个结论,是基于我做了大量的测试的基础上,至于为什么得到这个结果我当时也很迷惑
还好,在ECMA的文档中找到了证据,大家可以研究下文档中的概念,结合我的测试结果,不难理解JS整个对象机制

晕 哪能这么读文档呢
既然要看 有些地方就要看全吧,哪能带着主观的想法去看 找支撑自己观点东西啊。

这段说的是内置的Function函数
内置的Function Array RegExp直接调用跟new完全等价是显然的
人家可没说你自己写的
function F(){
    return function(){}
}
也能做到
var f = new F();
和f = F(); 2者是等价的

去看看11.2和13.2是怎么说的吧
0 请登录后投票
   发表时间:2008-06-24  
When the [[Construct]] property for a Function object F is called, the following steps are taken:
1. Create a new native ECMAScript object.
2. Set the [[Class]] property of Result(1) to "Object".
3. Get the value of the prototype property of the F.
4. If Result(3) is an object, set the [[Prototype]] property of Result(1) to Result(3).
5. If Result(3) is not an object, set the [[Prototype]] property of Result(1) to the original Object
prototype object as described in 15.2.3.1.
6. Invoke the [[Call]] property of F, providing Result(1) as the this value and providing the argument
list passed into [[Construct]] as the argument values.
7. If Type(Result(6)) is Object then return Result(6).
8. Return Result(1).

人家说的很清楚 如果函数call返回的是Object 那就返回call的返回值
否则返回新建的object
0 请登录后投票
   发表时间:2008-06-24  
csf177 写道
When the [[Construct]] property for a Function object F is called, the following steps are taken:
1. Create a new native ECMAScript object.
2. Set the [[Class]] property of Result(1) to "Object".
3. Get the value of the prototype property of the F.
4. If Result(3) is an object, set the [[Prototype]] property of Result(1) to Result(3).
5. If Result(3) is not an object, set the [[Prototype]] property of Result(1) to the original Object
prototype object as described in 15.2.3.1.
6. Invoke the [[Call]] property of F, providing Result(1) as the this value and providing the argument
list passed into [[Construct]] as the argument values.
7. If Type(Result(6)) is Object then return Result(6).
8. Return Result(1).

人家说的很清楚 如果函数call返回的是Object 那就返回call的返回值
否则返回新建的object


我在文中进行测试分析的时候猜测JS的机制就是这样,JS会根据call返回值得不同而产生不同的类型,现在看来是有了依据
所以
var f = function() {
this.a = b;
return function() {}
}

var f = function() {
this.a = b;
return null;
}
为什么前面的 "this" 会消失,这样就不难解释了
0 请登录后投票
   发表时间:2008-06-24  
- -!这样也可以靠上 你明明连词法关系都没搞对...... 人家new跟函数调用是两种表达式 只不过是长得很像 都带括号而已
算了不说了 能看懂ECMA262的人太少了 明明就那么几行英文 真无奈

设计一个貌似可爱的脚本能让一大半的使用者都看不懂标准文档 该说Brendan Eich水平高还是说他悲哀? 或者,二者兼有......
0 请登录后投票
   发表时间:2008-06-24  
引用

问题时JS的造物主是可以直接问的......BE大人还在世 而且ECMA也说得很清楚......
不需要这样推测......

而且正因为你的推测有错误 我才提醒你的 比如
f()和new f()的区别 我可以大概说一下
new f()一定构造了一个Object作为this的值 这个Object的原型是f.prototype 它将作为f的this值
如果f返回值为object 那么表达式new f()返回值是和f()的返回值是相同的
否则new f()会返回this

还有很多地方 你的说法不能算错 但是其实思路是错的


您提到的文档引用和您的观点刚好相矛盾
0 请登录后投票
   发表时间:2008-06-24  
csf177 写道
- -!这样也可以靠上 你明明连词法关系都没搞对...... 人家new跟函数调用是两种表达式 只不过是长得很像 都带括号而已
算了不说了 能看懂ECMA262的人太少了 明明就那么几行英文 真无奈

设计一个貌似可爱的脚本能让一大半的使用者都看不懂标准文档 该说Brendan Eich水平高还是说他悲哀? 或者,二者兼有......


我已经重复了好几遍了,文中提到概念都是现象到本质的推理,既然现在搬出了ECMA262的文档,就能圆满的解释我全部测试中提出的假设了。
并且文档中提到的和我推理的并无出入的地方,只不过一个概念化了,一个出于假设阶段而已
希望您认真读了我的文章,并且自己将全部例子跑一遍之后再进行评论,而不要断章取义。
我上述所阐述的并无不对,只不过没有必要咬文嚼字
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics