代码
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
}
}
var p1 = new Person('zs',20,'Doctor');
var p2 = new Person('ls',30,'Teachter');
复制代码
分析
-
要创建Person的新实例,必须使用new操作符。以这种方式调用构造函数实际会经历以下四个步骤:
1).创建一个新对象;
2).将这个构造函数的作用域赋给新对象(因此this就指向了这个新对象)
3).执行构造函数中的代码(为这个新对象添加属性);
4).返回新对象。
-
在前面例子的最后,p1和p2分别保存着Person的不同实例。这两个对象都有一个constructor(构造函数)属性,该属性指向Person(构造函数):
console.log(p1.constructor === Person);//true console.log(p2.constructor === Person);//true 复制代码
并且这两个实例可以链接到构造函数的原型:
console.log(p1.__proto__ === Person.prototype);//true console.log(p2.__proto__ === Person.prototype);//true 复制代码
可以通过
instanceof
检查对象的类型 (所有的对象均继承于Object)console.log(p1 instanceof Person);//true console.log(p1 instanceof Object);//true console.log(p2 instanceof Person);//true console.log(p2 instanceof Object);//true 复制代码
-
将构造函数当做普通函数调用,执行这个构造函数里面的代码,并且返回的this指向window
Person('zs',20,'Doctor');//不使用new操作符 复制代码
-
构造函数的问题
使用构造函数的主要问题,就是每个方法都在每个实例上重新创建一遍。(ECMAScript中函数是对象,因此每定义了一个函数,也就是实例化了一个对象)
不同实例的同名函数不相等(方法不共享):
console.log(p1.sayName == p2.sayName);//false 复制代码
解决方法,将函数的定义放在构造函数外部。
function Person(/**/){ this.sayName = sayName; } function sayName(){ alert(this.name); } 复制代码
此时会有一个问题,将一个方法定义在全局作用域中仅被某个对象调用,这让全局作用域名不副实。如果构造函数有很多的方法,那么就要定义很多的全局函数。