您是否曾困惑于 Javascript 中的new关键字呢?是否曾想理解关于 function 和 constructor 的区别是什么呢?javascript
大多数 Javascript 的新开发者不太想要使用new关键字,由于这会让代码写的像是 Java 而且在使用上会形成一点混乱;在这篇文章我会尽可能尝试着去理清这些东西,并解释它是如何运做的。java
constructor
翻为构造器但为了让您以后更好地理解,会直接使用 constructor
;在 Javascript 中任何一个函数(function
)均可以被看成 constructor
;Javascript 并无明确的区分二者,也就是说 function
能够被看成 constructor
或者看成通常函数调用。git
而 constructor
的用法就是 function
搭配new
关键字:github
function Person ( ) {
this . firstName = 'Jay' ;
this . lastName = 'Chou' ;
}
var person = new Person ( ) ;
console . log ( person ) ;
复制代码
接着咱们把person
呼叫出来看,会获得以下的结果,经过new
它会帮咱们创建一个对象,而后里面有Person
这个function
里面的内容,而且变成了属性名称和属性值:chrome
当使用new
命令时,它后面的函数依次执行下面的4个步骤:数组
prototype
属性。this
关键字。new
表达式中的函数调用会自动返回这个新对象。也就是说,当咱们使用new
这个关键字时,实际上会先有一个空的对象被创建。app
接着People
这个构造函数会被执行,这个空对象的原型,指向了People.prototype
。函数
咱们知道当函数执行的时候,在execution context
中会有this
被创建,而当咱们使用new
的时候,函数里面的this
会被指定成刚刚所创建的那个空对象。ui
因此当执行People
这个function
,执行到this.firstName
和this.lastName
时,由于this
如今指称的是那个空对象,因此其实是在帮这个空对象赋予属性名称和属性值。this
在这样的过程当中,只要这个构造函数People
没有指定return
为其余对象,它就会直接返回给咱们这个新创建的对象。
接着让咱们经过一段代码来更清楚的了解这个执行的过程:
function Person ( ) {
this . firstName = 'Jay' ;
this . lastName = 'Chou' ;
console . log ( '这个函数有被执行' ) ;
}
var person = new Person ( ) ;
console . log ( person ) ;
复制代码
这时候在chrome 中呼叫出来的结果以下,说明了当咱们使用new
在构造对象的时候People
这个function
确实有被执行:
如今我把咱们上面的代码改为这样:
function Person ( ) {
console . log ( this ) ;
}
var person = new Person ( ) ;
// console.log(person);
复制代码
这时候代码返回的结果以下,表示的确在执行这段代码的过程当中帮咱们创建了一个新的空对象:
如今,让咱们把本来的代码稍微作以下修改:
function Person ( ) {
this . firstName = 'Jay' ;
this . lastName = 'Chou' ;
return { "RETURN" : "本来this的内容就不会被返回" } ;
}
var person = new Person ( ) ;
console . log ( person ) ;
复制代码
构造函数的内部若return
其余对象,new
命令会返回return
语句指定的对象,将原新对象内容覆盖掉;不然,就会无论return
语句,返回this
对象。返回的结果以下:
function create() {
// 建立一个空的对象
var obj = new Object(),
// 得到构造函数,arguments中去除第一个参数
Con = [].shift.call(arguments);
// 连接到原型,obj 能够访问到构造函数原型中的属性
obj.__proto__ = Con.prototype;
// 绑定 this 实现继承,obj 能够访问到构造函数中的属性
var ret = Con.apply(obj, arguments);
// 优先返回构造函数返回的对象
return ret instanceof Object ? ret : obj;
};
复制代码
使用这个手写的new
function Person() {...}
// 使用内置函数new
var person = new Person(...)
// 使用手写的new,即create
var person = create(Person, ...)
复制代码
代码原理解析:
new Object()
的方式新建了一个对象obj
shift
会修改原数组,因此 arguments
会被去除第一个参数obj
的原型指向构造函数,这样obj
就能够访问到构造函数原型中的属性apply
,改变构造函数 this
的指向到新建的对象,这样 obj
就能够访问到构造函数中的属性obj
由上面的方法,咱们能够经过function
的方式来创建一个新的对象,若是咱们想要创建出同属性名称但不一样属性值的对象内容,咱们能够把对象的属性值变成参数,如此就能经过此function constructor
创建出许多不一样的对象:
function Person ( firstName , lastName ) {
this . firstName = firstName ;
this . lastName = lastName ;
}
var person1 = new Person ( 'Jay' , 'chou' ) ;
console . log ( person1 ) ;
var person2 = new Person ( 'Jane' , 'chou' ) ;
console . log ( person2 ) ;
复制代码
如此,咱们就能够经过同一个构造函数创建出不少不一样的对象:
此外,咱们会把根据构造器(constructor
)所创建出来的对象称做是实例(instance
),这在以前的文章里也有提过。
这里有一个地方咱们须要很是留意,若是你在撰写代码的过程中,忘记加上new
这个关键字的话,好比:
function Person ( ) {
this . firstName = 'Jay' ;
this . lastName = 'Chou' ;
}
var person = Person ( ) ;
console . log ( person ) ;
复制代码
如此,由于JavaScript不知道你是要执行这个函数,仍是要根据这个function
去创建object
,因次最后会返回undefined
的结果。
那又是如何经过function constructors
来设定咱们的原型(prototype
)呢?让咱们在下一篇文章来谈吧!
若是以为文章对你有些许帮助,欢迎在个人GitHub博客点赞和关注,感激涕零!