造函数其实和普通函数本质上并无区别,唯一的区别有两个:

函数首字母大写,这个区别只是约定俗成的,便于区分。你实在要小写定义构造函数也完全没问题,所以这个区别可以忽略。
构造函数的调用需要用new操作符,而普通函数的调用又分很多种,但是都不会用到new操作符。所以,构造函数和普通函数的区别就在这个new操作符里,现在让我们来好好研究一下这个new操作符。

用new操作符创建对象时发生的事情:

(1)创建一个新对象;

(2)将构造函数的作用域赋给新对象(因此this就指向了这个新对象);

(3)执行构造函数中的代码(为这个新对象添加属性和方法);

(4)返回新对象;

通过new操作符后跟构造函数的方式创建的对象(实例),这个对象有一个constructor(构造函数)属性,该属性指向构造函数Person。

创建的对象,毫无疑问是Person的实例,同时也是Object的实例;所有对象皆继承自Object。

构造函数是定义在Global对象中的,在浏览器中,即为window对象。

注意:原本的构造函数是window对象的方法,如果不用new操作符而直接调用,那么构造函数的执行对象就 是window,即this指向了window。现在用new操作符后,this就指向了新生成的对象。理解这一步至关重要。
执行构造函数中的代码,看代码:

function Person(){
  this.name = "Tiny Colder";
  var age = 22;
  window.age = 22;
}
var p = new Person();
alert(p.name)//Tiny Colder;
alert(p.age)//undefined;
alert(window.age)//22;

当用new操作符创建对象时,先创建了一个对象实例,然后执行代码。所以还在纠结,什么时候构造函数定义的属性会继承给实例对象的,都可以这么来看:

var p = new Object();
p.name = "Tiny Colder";

这是普通的创建对象,然后给对象添加属性的方法。如果每创建一个对象,都需要这么几行代码,无疑是糟糕的。这个需求就正好跟这一点对应:new操作符,自动执行构造函数里的代码。如此我们便可以省掉添加属性时重复冗余的代码。那么这些属性时如何添加到新生成的对象里的呢?

第二个步骤里已经说了:将构造函数的执行对象赋给新生成的这个实例。再结合上一段里说的,自动执行构造函数里的this.name = "Tiny Colder";时,就相当于是执行p.name = "Tiny Colder";而构造函数里的var age = 22;语句,会执行但是对新生成的对象并无影响。window.age = 22;语句,会执行,且会给window对象添加一个属性。alert为证。
或许到这里,你已经理解了new操作符的前三步了,重要的三步。但是这个函数是如何返回对象的呢?我们并没有看到有任何跟return相关的语句。这就是new操作符的最后一步:返回新生成的对象。
如果被调用的函数没有显式的 return 表达式(仅限于返回对象),则隐式的会返回 this 对象 - 也就是新创建的对象。
现在来看一下这个代码:
function Person(){
this.name = "Tiny Colder";
return {};
}
var p = new Person();
alert(p.name)//undefined;

一个对象就这么被创建出来了。
实际上,

var p = new Person();


var p = new Object();
Person.apply(p);
是一样的效果。

构造函数也是函数

任何函数,只要通过new操作符来调用,那么它就可以作为构造函数;任何函数,如果不通过new操作符来调用,那它与普通函数并无区别。

(1)当做构造函数调用

var person = new Person("CC",23);

(2)当做普通函数使用

Person("CC",23);    //添加到window对象
console.log(window.name); //"CC"
console.log(window.age); //23

(3)在另一个对象的作用域中调用

var person = new Object();
Person.call(person,"CC",23);
console.log(person.name); //"CC"
console.log(person.age); //

构造函数的问题

使用构造函数的主要问题,就是每个方法都要在每个实例上重新创建一次。

var person1 = new Person("CC",23);
var person2 = new Person("VV",32);

两个实例都有sayName()方法,但是两个方法不是同一Function的实例,也就是说,两个实例上的同名函数是不相等的。

console.log(person1.sayName == person2.sayName);    //false

JS构造函数new的过程的更多相关文章

  1. JS构造函数的用法和JS原型

    $(function(){ var rec = new Rectangle(5, 10); //alert(rec.width + "*" + rec.height + " ...

  2. 谈谈JS构造函数

    //构造函数 //使自己的对象多次复制,同时实例根据设置的访问等级可以访问其内部的属性和方法 //当对象被实例化后,构造函数会立即执行它所包含的任何代码 function myObject(msg) ...

  3. Class和普通js构造函数的区别

    Class 在语法上更加贴合面向对象的写法 Class 实现继承更加易读.易理解 更易于写 java 等后端语言的使用 本质还是语法糖,使用 prototype Class语法 typeof Math ...

  4. c++中六种构造函数的实现以及9中情况下,构造函数的调用过程

    六种构造函数的实现代码例如以下: #include<iostream> using namespace std; //c++中六种默认的构造函数 class Test { public: ...

  5. C++ 构造函数的执行过程(一) 无继承

      引言 C++ 构造函数的执行过程(一) 无继承 本篇介绍了在无继承情况下, C++构造函数的执行过程, 即成员变量的构建先于函数体的执行, 初始化列表的数量和顺序并不对构造函数执行顺序造成任何影响 ...

  6. (转载)js引擎的执行过程(二)

    概述 js引擎执行过程主要分为三个阶段,分别是语法分析,预编译和执行阶段,上篇文章我们介绍了语法分析和预编译阶段,那么我们先做个简单概括,如下: 语法分析: 分别对加载完成的代码块进行语法检验,语法正 ...

  7. (转载)js引擎的执行过程(一)

    概述 js是一种非常灵活的语言,理解js引擎的执行过程对我们学习javascript非常重要,但是网上讲解js引擎的文章也大多是浅尝辄止或者只局部分析,例如只分析事件循环(Event Loop)或者变 ...

  8. js 构造函数 & 静态方法 & 原型 & 实例方法

    js 构造函数 & 静态方法 & 原型 & 实例方法 ES5 "use strict"; /** * * @author xgqfrms * @licens ...

  9. js构造函数,索引数组和属性的属性

    本文主要介绍和小结js的构造函数,关联数组的实现方式和使用,及不可变对象和它的实现方式及他们使用过程中要注意的点 <script> function p(){ var len=argume ...

随机推荐

  1. python异常值(outlier)检测实战:KMeans + PCA + IsolationForest + SVM + EllipticEnvelope

    机器学习_深度学习_入门经典(博主永久免费教学视频系列) https://study.163.com/course/courseMain.htm?courseId=1006390023&sha ...

  2. Oracle的“ORA-00937: 不是单组分组函数” 如何解决?

    之前在编写oracle的sql语句时遇到这个问题,这里做个记录 问题描述:ORA-00937: 不是单组分组函数 问题原因:select语句中又在查询某一列的值,其中还有聚合函数 原先本人编写SQL是 ...

  3. Class-SP:Order.cs

    ylbtech-Class-SP:Order.cs 1. 返回顶部 1.GoodsType.cs 货品类别 using System; using System.Collections.Generic ...

  4. docker run启动的容器挂掉了,数据怎么办

    情景描述 在某个系统中,功能性的服务使用 docker stack deploy xxx 启动,某个国产数据库的服务单独使用 docker run xxx 启动,数据库服务没有将存储的位置挂载出来: ...

  5. Ubuntu 16.04 Roboware安装和使用

    博客参考:https://blog.csdn.net/qq_41450811/article/details/80305846 RoboWare Studio是一个ROS集成开发环境.它使 ROS开发 ...

  6. Eclipse笔记-sun.misc.BASE64Encoder找不到jar包的解决方法

    从SVN检出新项目,在Eclipse中报错如下: 转: Eclipse笔记-sun.misc.BASE64Encoder找不到jar包的解决方法 2018-01-04 00:36:20 雨临Lewis ...

  7. pytorch使用DataParallel并行化负载不均衡问题

    使用DataParallel进行并行化时的结构如下: 在上图第一行第四个步骤中,GPU-1 其实汇集了所有 GPU 的运算结果.这个对于多分类问题还好,但如果是自然语言处理模型就会出现问题,导致 GP ...

  8. Zabbix主动模式与被动模式的区别——最简单的解释

    一直搞不清楚Zabbix的主动模式和被动模式的差别,网上看到别人博客里的解释都是云里雾里的,完全搞不清.知道偶然看到了以下这个解释.就基本上明白了. Zabbix的主动模式和被动模式都是相对agent ...

  9. Python unittest(PyUnit)单元测试框架

    PyUnit(unittest) 是 Python 自带的单元测试框架,用于编写和运行可重复的测试.PyUnit 是 xUnit 体系的一个成员,xUnit 是众多测试框架的总称,PyUnit 主要用 ...

  10. 基于zynq 7020的串口UART中断实验

    1.参考 UG585,P1790[JokerのZYNQ7020]UART学会Zynq(27)UART中断驱动模式示例 2.理论知识 在ZYNQ的中断中有一个IOP的中断集,它包几个外设的中断,其中包含 ...