考察 ECMAScript 语言规范中 new 运算符的定义:

The new Operator

The production NewExpression : new NewExpression is evaluated as follows:

  1. Evaluate NewExpression.
  2. Call GetValue(Result(1)).
  3. If Type(Result(2)) is not Object, throw a TypeError exception.
  4. If Result(2) does not implement the internal [[Construct]] method, throw a TypeError exception.
  5. Call the [[Construct]] method on Result(2), providing no arguments (that is, an empty list of arguments).
  6. Return Result(5).

注意到,这段定义中的 new 后的表达式不带参数,即是说,这段内容针对的是诸如 obj = new Object; 这样的用法——带参数的用法如 str = new String(“test”); 将在下面给出。两者有区别且区别不大。

回到上述定义,其大意是,new 后必须跟一个对象并且此对象必须有一个名为 [[Construct]] 的内部方法(其实这种对象就是构造器),否则会抛出异常,比如:

var Str = "test";
var aStr = new Str;
// FF 显示“Str is not a constructor”
// IE 显示“对象不支持此操作”

var Num = new Number(999);
var aNum = new Num;
// 结果同上

如果符合以上条件,那么引擎将调用其 [[Construct]] 内部方法,并不提供入口参数。接下来便要考察此内部方法。

另外,下面一段是 new 运算符的带参用法,由于和无参用法区别不大,读者朋友可直接略过。

The production MemberExpression : new MemberExpression Arguments is evaluated as follows:

  1. Evaluate MemberExpression.
  2. Call GetValue(Result(1)).
  3. Evaluate Arguments, producing an internal list of argument values (11.2.4).
  4. If Type(Result(2)) is not Object, throw a TypeError exception.
  5. If Result(2) does not implement the internal [[Construct]] method, throw a TypeError exception.
  6. Call the [[Construct]] method on Result(2), providing the list Result(3) as the argument values.
  7. Return Result(6).

考察 [[Construct]] 内部方法,先给出语言规范的描述:

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).

引擎将先创建一个语言原生对象,即“{}”或“new Object”,在此我们称之为 O,然后设置其内部属性标识 [[Class]] 为“Object”。接下来,得到构造器 F 的 prototype(根据后文的意思,它可能不是一个对象)。如果 F.prototype 是对象,那么将 O 的内部 [[Prototype]] 属性指向 F.prototype。

请注意,诸如 [[Prototype]] 等为引擎内部标识符,对我们并不可见。[[Prototype]] 正是用于给内部维护原型链,虽然在我们看来,一个对象实例无法直接回溯到其原型(然而引擎内部可以),必须通过构造器中转,即 obj.constructor.prototype。

接着,如果 F.prototype 不是 object,那么将 O 的内部 [[Prototype]] 属性指向“the Object prototype object”(你可以参考这里)。等到 O 的 [[Prototype]] 有了自己的归属以后,引擎调用构造器 F 的 [[Call]] 内部方法,以 O 作为 this 对象,并将传入 [[Construct]] 的参数作为入口参数——如果有的话(即诸如“new Object()”最后括号内的参数)传递过去。最后,如果 [[Call]] 的返回值是对象,那么创建成功并返回此对象,否则回头重来。

根据这些内容,我们完全可以构造一个伪 [[Construct]] 方法来模拟此流程(其实已有众多前辈做过此工作):

function MyObject(age) {
    this.age = age;
}

MyObject.construct = function() {
    var o = {}, Constructor = MyObject;
    o.__proto__ = Constructor.prototype;
    // FF 支持用户引用内部属性 [[Prototype]]

    Constructor.apply(o, arguments);
    return o;
};

var obj1 = new MyObject(10);
var obj2 = MyObject.construct(10);
alert(obj2 instanceof MyObject);
// true

到此,new 运算的过程已经描述得足够清楚了

http://www.pushiming.com/blog/2009/10/the-new-operator/

javascript的中的new的更多相关文章

  1. JavaScript jQuery 中定义数组与操作及jquery数组操作

    首先给大家介绍javascript jquery中定义数组与操作的相关知识,具体内容如下所示: 1.认识数组 数组就是某类数据的集合,数据类型可以是整型.字符串.甚至是对象Javascript不支持多 ...

  2. JavaScript文件中调用AngularJS内部方法或改变$scope变量

    需要在其他JavaScript文件中调用AngularJS内部方法或改变$scope变量,同时还要保持双向数据绑定: 首先获取AngularJS application: 方法一:通过controll ...

  3. JavaScript ES7 中使用 async/await 解决回调函数嵌套问题

    原文链接:http://aisk.me/using-async-await-to-avoid-callback-hell/ JavaScript 中最蛋疼的事情莫过于回调函数嵌套问题.以往在浏览器中, ...

  4. 警惕javascript代码中的“</script>”!

    之前在写<博客园自定义博客侧边栏公告的过滤漏洞>的时候遇到了一个javascript代码报错“语法错误”的问题,一直不得以解决,感谢Arliang发现了并为我进行了耐心的解释,现整理如下: ...

  5. [记录] javascript 对象中使用setTimeout

    参考:Javascript对象中关于setTimeout和setInterval的this介绍 使用最后一个方法终于弄好了,简直了,在对象中使用setTimeout原来是这样的 做的是分钟倒计时,倒数 ...

  6. 第一百节,JavaScript表达式中的运算符

    JavaScript表达式中的运算符 学习要点: 1.什么是表达式 2.一元运算符 3.算术运算符 4.关系运算符 5.逻辑运算符 6.*位运算符 7.赋值运算符 8.其他运算符 9.运算符优先级 E ...

  7. Javascript Jquery 中的数组定义与操作_子木玲_新浪博客

    body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...

  8. JavaScript 语言中的 this

    JavaScript 语言中的 this 由于其运行期绑定的特性,JavaScript 中的 this 含义要丰富得多,它可以是全局对象.当前对象或者任意对象,这完全取决于函数的调用方式.JavaSc ...

  9. JavaScript面向对象中的继承

    1.1继承的基本概念 使用一个子类,继承另一个父类,那么子类可以自动拥有父类中的所有属性和方法,这个过程叫做继承. >>>继承的两方,发生在两个类之间. 实现继承的三种方式: 扩展O ...

  10. JavaScript ES6中export及export default的区别

    相信很多人都使用过export.export default.import,然而它们到底有什么区别呢? 在JavaScript ES6中,export与export default均可用于导出常量.函 ...

随机推荐

  1. hadoop 集群配置--增加减少新的机器不重启

    增加机器不重启操作如下: 首先,把新节点的 IP或主机名 加入主节点(master)的 conf/slaves 文件. 然后登录新的从节点,执行以下命令: $ cd path/to/hadoop $ ...

  2. hdu4965矩阵快速幂

    这题不能直接按常规做啊,因为数组根本就开不下,转换思维A(B*A)^(n*n-1)B 这样的话数组B*A就是10*10了,然后快速幂就行了 刚开始数组都开小了,tle,还找了半天bug...还有就是定 ...

  3. Java网络编程和NIO详解2:JAVA NIO一步步构建IO多路复用的请求模型

    Java网络编程与NIO详解2:JAVA NIO一步步构建IO多路复用的请求模型 知识点 nio 下 I/O 阻塞与非阻塞实现 SocketChannel 介绍 I/O 多路复用的原理 事件选择器与 ...

  4. UVALive-3415 Guardian of Decency (最大独立集)

    题目大意:一个老师要带一些学生去春游,但是要带的学生中任意两个人都满足下面四个条件中的至少一个:1.性别相同:2.身高差大与40公分:3.最喜欢的音乐类型不同:4.最喜欢的体育运动相同.问老师最多能带 ...

  5. Java9新特性

    转载:http://blog.csdn.net/qq_32524177/article/details/77014757 写在前面的话:Java9来了,搜索了很多关于Java9的新特性,但文献不多,特 ...

  6. 16款最受关注的智能手表 苹果iWatch领衔

    智能手表逐渐成为科技行业的新宠,而传闻中的苹果iWatch以及已经确认即将推出的三星Galaxy Gear,显然让这股热潮达到了顶峰,也预示着大牌厂商将逐渐进入该领域,推出更多成熟的产品.以下便是16 ...

  7. 趣谈StateServer在Web Garden,Web Farm下的使用

    上一篇翻译的博客[译文]漫谈ASP.NET中的Session已经介绍了Session的基础知识,如果看过了的话对Session应该有了一个比较清晰的认识了,现在我来谈谈我所遇到的困境以及对Sessio ...

  8. L203 词汇题

    Conditions for the growth of this plant are optimum in early summer.we will live as free people, not ...

  9. OMAP4之DSP核(Tesla)软件开发学习(三)使能DSP核

    目标: 1.编译或直接获取DSP映像tesla-dsp.bin. 2.boot并使能DSP核(这个可以看启动打印或者进入/d/remoteproc/omap-rproc.0/参看dsp调试信息).   ...

  10. HTML, CSS. JS的各种奇淫技巧

    1. js 中为了省字节,性能, 防止被重写等发明了各种写法,记录下 //取整 parseInt(a,10); //Before Math.floor(a); //Before a>>0; ...