构造函数:
构造函数其实就是一个使 用new操作符调用的函数。当使用 new 调用时,构造函数内用到的this对象会指向新创建的对象实例.
// 构造函数示例:
var Person = function(name,age){
this.name = name
this.age = age
this.getInfo = function(){
return this.name+':年龄 '+this.age
}
}
var p1 = new Person('张三',18)
console.log(p1.getInfo()) // 张三:年龄 18
上述例子中,Person构造函数使用this对象给三个属性赋值:name、age和getInfo。当和new操作符连用时,则会创建一个新的 Person 对象,同时会给它分配这些属性。
但是,由于该 this对象是在运行时绑定的,如果没有使用 new 操作符直接调用 Person(), this 会映射到全局对象 window上,导致错误对象属性的意外增加。
var p2 = Person('张三',18)
console.log(window.name,window.age) // '张三' 18
此时,由于 window 的 name 属性是用于识别链接目标和 frame 的,所以这里对该属性的偶然覆盖可能会导致该页面上出现其他错误。
这个问题的解决方法就是创建一个作用域安全的构造函数.
// 作用域安全的构造函数
var Person = function(name,age){
if (this instanceof Person) {
this.name = name
this.age = age
this.getInfo = function() {
return this.name+':年龄 '+this.age
}
} else {
return new Person(name, age)
}
}
以上,稍微改造后,确保this对象是 Person 的实例,即:要么使用new操作符,要么在现有的Person实例环境中调用构造函数。任何一种情况下,对象初 始化都能正常进行,避免了在全局对象上意外设置属性。
不过使用作用域安全的构造函数,在下述情况下,会有问题。
var Person2 = function(gentle){
Person.call(this,'李四',20)
}
var p2 = new Person2('male');
console.log(p2.name) // undefined
由于Person构造函数是作用域安全的,this 对象并非 Person2 的实例,所以导致,Person中的this,并不指向Person2的实例p2.Person2构造函数中的 this对象并没有得到增长.p2中,也就不会有Person中的属性,name,age,getInfo.
如果p2要继承Person的属性,可作下述更改
// 将Person2的prototype属性,指向Person的实例,这里又涉及到了对象的继承,下个系列跟进
var Person2 = function(height){
Person.call(this,'李四',20)
this.height = height
this.showInfo = function(){
console.log(this.height)
}
}
Person2.prototype = new Person()
var p2 = new Person2(180);
console.log(p2)// {name: "李四", height: 180, getInfo: ƒ, showInfo: ƒ}