揭开js之constructor属性的神秘面纱

在js里面当new了一个对象时,这中间发生了什么?

MDN - new运算符

当代码 new foo(...) 执行时:

  1. 一个新对象被创建。它继承自foo.prototype.
  2. 构造函数 foo 被执行。执行的时候,相应的传参会被传入,同时上下文(this)会被指定为这个新实例。new foo 等同于 new foo(), 只能用在不传递任何参数的情况。
  3. 如果构造函数返回了一个“对象”,那么这个对象会取代整个new出来的结果。如果构造函数没有返回对象,那么new出来的结果为步骤1创建的对象。(一般情况下构造函数不返回任何值,不过用户如果想覆盖这个返回值,可以自己选择返回一个普通对象来覆盖。当然,返回数组也会覆盖,因为数组也是对象。)

What is the 'new' keyword in JavaScript?

It does 5 things:

  1. It creates a new object. The type of this object, is simply object.
  2. It sets this new object's internal, inaccessible, [[prototype]] (i.e. proto) property to be the constructor function's external, accessible, prototype object (every function object automatically has a prototype property).
  3. It makes the this variable point to the newly created object.
  4. It executes the constructor function, using the newly created object whenever this is mentioned.
  5. It returns the newly created object, unless the constructor function returns a non-null object reference. In this case, that object reference is returned instead.

Note: constructor function refers the function after the new keyword, as in

new ConstructorFunction(arg1, arg2)

Once this is done, if an undefined property of the new object is requested, the script will check the object's [[prototype]] object for the property instead. This is how you can get something similar to traditional class inheritance in JavaScript.

The most difficult part about this is point number 2. Every object (including functions) has this internal property called [[prototype]]. It can only be set at object creation time, either with new, with Object.create, or based on the literal (functions default to Function.prototype, numbers to Number.prototype, etc.). It can only be read with Object.getPrototypeOf(someObject). There is no other way to set or read this value.

Functions, in addition to the hidden [[prototype]] property, also have a property called prototype, and it is this that you can access, and modify, to provide inherited properties and methods for the objects you make.

Here is an example:

ObjMaker = function() {this.a = 'first';};
// ObjMaker is just a function, there's nothing special about it that makes
// it a constructor. ObjMaker.prototype.b = 'second';
// like all functions, ObjMaker has an accessible prototype property that
// we can alter. I just added a property called 'b' to it. Like
// all objects, ObjMaker also has an inaccessible [[prototype]] property
// that we can't do anything with obj1 = new ObjMaker();
// 3 things just happened.
// A new, empty object was created called obj1. At first obj1 was the same
// as {}. The [[prototype]] property of obj1 was then set to the current
// object value of the ObjMaker.prototype (if ObjMaker.prototype is later
// assigned a new object value, obj1's [[prototype]] will not change, but you
// can alter the properties of ObjMaker.prototype to add to both the
// prototype and [[prototype]]). The ObjMaker function was executed, with
// obj1 in place of this... so obj1.a was set to 'first'. obj1.a;
// returns 'first'
obj1.b;
// obj1 doesn't have a property called 'b', so JavaScript checks
// its [[prototype]]. Its [[prototype]] is the same as ObjMaker.prototype
// ObjMaker.prototype has a property called 'b' with value 'second'
// returns 'second'
It's like class inheritance because now, any objects you make using new ObjMaker() will also appear to have inherited the 'b' property. If you want something like a subclass, then you do this: SubObjMaker = function () {};
SubObjMaker.prototype = new ObjMaker(); // note: this pattern is deprecated!
// Because we used 'new', the [[prototype]] property of SubObjMaker.prototype
// is now set to the object value of ObjMaker.prototype.
// The modern way to do this is with Object.create(), which was added in ECMAScript 5:
// SubObjMaker.prototype = Object.create(ObjMaker.prototype); SubObjMaker.prototype.c = 'third';
obj2 = new SubObjMaker();
// [[prototype]] property of obj2 is now set to SubObjMaker.prototype
// Remember that the [[prototype]] property of SubObjMaker.prototype
// is ObjMaker.prototype. So now obj2 has a prototype chain!
// obj2 ---> SubObjMaker.prototype ---> ObjMaker.prototype obj2.c;
// returns 'third', from SubObjMaker.prototype obj2.b;
// returns 'second', from ObjMaker.prototype obj2.a;
// returns 'first', from SubObjMaker.prototype, because SubObjMaker.prototype
// was created with the ObjMaker function, which assigned a for us

I read a ton of rubbish on this subject before finally finding this page, where this is explained very well with nice diagrams.

javascript constrator and prototype的更多相关文章

  1. 悟透Javascript之 原型prototype

    构造函数的Prototype上定义的方法确实可以通过对象直接调用,而且代码是共享的.我表示我不懂.太难理解了,艹.在Javascript中,prototype不但能让对象共享自己的财富,而且proto ...

  2. JavaScript -- 原型:prototype的使用

    JavaScript -- 原型:prototype的使用 在 JavaScript 中,prototype 是函数的一个属性,同时也是由构造函数创建的对象的一个属性. 函数的原型为对象. 它主要在函 ...

  3. JavaScript中的prototype和__proto__细致解析

    最近在学js,体会了一点点它的灵活性.对于初学者的我,总是被它的灵活感到晕头转向,最近发现了一点东西想与大家分享. JavaScript中的prototype和_proto_: 我们先了解一点js中的 ...

  4. C# -- 等待异步操作执行完成的方式 C# -- 使用委托 delegate 执行异步操作 JavaScript -- 原型:prototype的使用 DBHelper类连接数据库 MVC View中获取action、controller、area名称、参数

    C# -- 等待异步操作执行完成的方式 C# -- 等待异步操作执行完成的方式 1. 等待异步操作的完成,代码实现: class Program { static void Main(string[] ...

  5. JavaScript中Object.prototype.toString方法的原理

    在JavaScript中,想要判断某个对象值属于哪种内置类型,最靠谱的做法就是通过Object.prototype.toString方法. ? 1 2 var arr = []; console.lo ...

  6. javascript里的prototype

    在javascript中,prototype是函数的一个固有属性,其他对象,比如字符串什么的,并没有这个属性. 这个属性做什么用呢? 1.用于该函数的所有实例进行共享 比如,共同的属性,共同的方法.类 ...

  7. JavaScript原型链:prototype与__proto__

    title: 'JavaScript原型链:prototype与__proto__' toc: false date: 2018-09-04 11:16:54 主要看了这一篇,讲解的很清晰,最主要的一 ...

  8. 谈谈javascript中的prototype与继承

    谈谈javascript中的prototype与继承 今天想谈谈javascript中的prototype. 通常来说,javascript中的对象就是一个指向prototype的指针和一个自身的属性 ...

  9. javascript入门:prototype和面向对象的实现

    由于工作需要,需要大量使用javascript,于是对其进行了一下学习. 学习任何一个语言,最重要的是掌握其和其他语言不同的关键特性.对javascript来说,我总结就是prototype.就像me ...

随机推荐

  1. LeakCanary,30分钟从入门到精通

    简述 在性能优化中,内存是一个不得不聊的话题:然而内存泄漏,显示已经成为内存优化的一个重量级的方向.当前流行的内存泄漏分析工具中,不得不提的就是LeakCanary框架:这是一个集成方便, 使用便捷, ...

  2. MyEclipse的破解和汉化方法

    一.安装和破解 我的MyEclipse是从官网下的正版软件,在其他地方下载的版本同理. 官方下载地址(需FQ): http://www.myeclipseide.com/module-htmlpage ...

  3. Linux下创建可执行bin安装文件

    需求及应用场景 1.简化操作.一般的软件安装过程,如果想要精简步骤,我们一般会将需要在命令行中输入的命令写成一个脚本,同时将安装介质准备好.我们将脚本和安装介质上传到生产环境,然后通过执行脚本来完成安 ...

  4. 安卓之上传文件,即HTTP提交表单

    获取文件: public void Init()    {        noScrollgridview = (GridView) findViewById(R.id.noScrollgridvie ...

  5. endnote插入参考文献后的对齐方式和缩进空格

    原文链接 https://jingyan.baidu.com/article/63acb44a3f0f6161fcc17ed0.html 1 2 3 4 5 6 7 分步阅读 1.endnote 导入 ...

  6. [转]Sqoop-1.4.4工具import和export使用详解

    FROM :http://shiyanjun.cn/archives/624.html Sqoop可以在HDFS/Hive和关系型数据库之间进行数据的导入导出,其中主要使用了import和export ...

  7. [转]如何将PHP作为Shell脚本语言使用

    From : http://www.linuxfly.org/post/559/ 我们都知道,PHP是一种非常好的动态网页开发语言(速度飞快,开发周期短……).但是只有很少数的人意识到PHP也可以很好 ...

  8. [转]让Nginx支持ThinkPHP的URL重写和PATHINFO

    From : http://www.jzxue.com/wangzhankaifa/php/201108/08-8396.html   ThinkPHP支持通过PATHINFO和URL rewrite ...

  9. IDEA 快速将spring boot项目打包成jar包,简单快速有效

    原文地址;https://blog.csdn.net/chen846262292/article/details/80701101  https://www.cnblogs.com/chrischen ...

  10. C/C++ 分支预测(likely unlikely)

    看一些代码时,会遇到likely unlikely, 查了查网上的资料,结合自己的理解记录一下. 1. 一些概念 指令周期是指执行一条指令所需要的时间,一般由若干个机器周期组成,是从取指令.分析指令到 ...