构造函数就是一个普通函数,创建方式和普通函数没有区别,构造函数和普通函数区别就是调用方式不同,普通函数直接调用,而构造和函数需要使用new关键字来调用。
构造函数执行的流程:
1.立刻创建一个新的对象
2.将新建的对象作为函数中的this 在构造函数中可以使用this来引用新建的对象
3.逐行执行函数中的代码
4.将新建对象作为返回值返回
如下例子
function Person(name,age,gender){
this.name = name; // this指向新创建的对象per
this.age = age;
this.gender = gender;
this.sayName = function(){
alert(this.name);
};
};
var per = new Person('孙悟空',19,'男');// 使用new关键字调用构造函数
var per2 = new Person('白骨精',20,'女');
var per3 = new Person('奔波霸',22,'女');
console.log(per);
console.log(per2);
console.log(per3);
instanceof关键字
使用instanceof可以检查一个对象是否是一个类的实例
console.log(对象 instanceof 构造函数)//true
先看下面的代码
function Person(name,age,gender){
this.name = name; // this指向per
this.age = age;
this.gender = gender;
this.sayName = function(){
alert(this.name);
};
};
var per = new Person('孙悟空',19,'男');// 使用new关键字调用构造函数
var per2 = new Person('孙悟空',19,'男');
console.log(per.sayName === per2.sayName); //false
可以发现实例per和实例per2的sayName方法并不相同,这是因为sayName方法是在构造函数内部创建的,构造函数每执行一次都会创建一个新的sayName方法,所有实例的sayName方法都是唯一的。
执行10000次就会创建 10000个新方法,而这 10000个新方法都是一摸一样的,这是完全没有必须的!!!完全可以使所有对象都共享一个方法!!!而这个对象就是原型对象!!!
原型(prototype)
我们所创建的每一个构造函数,解析器都会向构造函数中添加一个属性prototype,这个属性对应一个对象,这个对象就是我们所谓的原型对象
注意:如果函数作为普通函数调用prototype没有任何作用。
原型对象就相当于一个公共区域,所有构造函数的实例都可以访问到这个区域内的属性和方法,我们可以将共有的内容统一设置到原型对象中,当我们访问对象的一个属性或方法,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找。做为构造函数的实例对象也有一个隐含属性__proto__,实例的这个属性也对应原型对象。
再看下面代码
function Person(){
};
Person.prototype.a = 123;// 向Person的原型中添加属性a
Person.prototype.sayHello = function(){
// 向Person的原型中添加方法
console.log('hello');
}
var p = new Person();
var p2 = new Person();
console.log(p.sayHello===p2.sayHello);// true
console.log(p.__proto__ === Person.prototype);// true
console.log(p2.__proto__ === Person.prototype);// true
以后我们创建构造函数时,可以将这些原型对象共有的属性和方法 统一添加到构造函数的原型对象中,这样不用分别为每个对象添加,可以节省内存,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了。
in关键字
使用in关键字检查对象中是否含有某个属性时,如果对象中没有但原型中有也会返回true,否则返回false。
function MyClass(){
};
// 向MyClass的原型中添加一个name属性
MyClass.prototype.name = '我是原型中的名字';
var mc = new MyClass();
mc.age = 18;
console.log('name' in mc);// true
console.log('name' in MyClass);// true
console.log('age' in mc)// ture
console.log('age' in MyClass)// false
可以发现 name 属性作为原型对象的属性,实例虽然没有定义 name 属性,但仍然可以访问到 name 属性,而属性age不行,因为age不存在MyClass的原型对象里。
也可以使用对象的 hasOwnProperty() 来检查对象自身中是否含有该属性
function MyClass(){
}
// 向MyClass的原型中添加一个name属性
MyClass.prototype.name = '我是原型中的名字';
var mc = new MyClass();
mc.age = 18;
console.log(mc.name);
// 可以使用对象的hasOwnProperty()来检查对象自身中是否含有该属性
console.log(mc.hasOwnProperty('name'));// true
console.log(mc.hasOwnProperty('age'));// true