定义JS类
工厂模式
function Person (name) {
var o = new Object();
o.name = name;
o.sayName = function () {
alert(this.name);
};
return o;
}
var p = Person('Tom');
new一个object,给object添加属性,return object对象 缺点:无法识别对象的类型,都是Object
构造函数
function Person (name) {
this.name = name;
this.sayName = function () {
alert(this.name);
};
}
var p = new Person('Tom');
直接给this赋属性和方法,无需return,需要new一个实例对象,该实例对象的类型为构造函数Person 缺点:每个实例都会创建同样的方法sayName,即方法不能共享
原型模式
function Person () {};
Person.prototype.name = 'Tom';
Person.prototype.sayName = function () {
alert(this.name);
}
var p = new Person(); // p.name = Tom
var r = new Person();
r.name = 'Jerry'; // 导致p.name=Jerry
通过prototype来设置属性和方法,共享的 缺点:所有的实例共享方法和属性的引用,一个实例修改会影响所有的实例
组合构造函数和原型模式
function Person (name) {
this.name = name;
}
Person.prototype = {
constructor = Person;
sayName: function () {
alert(this.name);
};
}
var p = Person('Tom');
构造函数中定义实例属性,各个实例拥有自己的属性 原型中定义共享的方法 原型链:实例属性的查找,首先在查找实例属性,若没有,则向上查找,即查找其prototype指向的原型对象是否有该属性,依次向上直到Object
继承
原型链
function Super(name) {
this.name = name;
this.phone = [1,2,3];
}
Super.prototype.sex = 'female';
Super.prototype.sayName = function () {
alert(this.name);
}
function Sub(name,age) {
this.name = name;
this.age = age;
}
Sub.prototype = new Super('Tom');//原型具有父类的实例属性和方法,即拥有自己的name和phone
Sub.prototype.sayName = function () {
alert(this.name + this.age);
}
var obj1 = new Sub('Jerry', 23); // obj1.phone=[1,2,3]
var obj2 = new Sub('Chris', 18);// obj2.phone=[1,2,3]
obj1.phone.push(4);// obj2.phone=[1,2,3,4]
// obj1.__proto__ === Sub.prototype === obj2.__proto__
// obj1.phone === obj1.__proto__.phone
//obj1.phone === obj2.phone
子类的原型重写为父类的一个实例对象,子类拥有父类原型对象中的所有属性和方法,子类同名属性和方法会覆盖父类 子类的原型对象拥有父类实例对象的所有引用类型的属性(实例属性) 子类实例对引用类型的变更会影响到所有其他的实例中的该引用变量
借助构造函数
function Super(name) {
this.name = name;
this.sayName = function() {
alert(this.name);
}
}
function Sub(name, age) {
Super.call(this, name);
this.age = age;
}
构造函数中定义方法,所有实例都会创建一个函数,复用性差
组合原型链和构造函数
function Super(name) {
this.name = name;
this.phone = [1,2,3];
}
Super.prototype.sex = 'female';
Super.prototype.sayName = function () {
alert(this.name);
}
function Sub(name, age) {
Super.call(this, name); // 将属性绑定到this
this.age = age;
}
Sub.prototype = new Super();
Sub.prototype.sayAge = function () {
alert(this.age);
}
var obj1 = new Sub('A');
var obj2 = new Sub('B');
// obj1 obj2分别拥有自己的phone属性
// Sub.prototype.phone != obj1.phone
原型链实现原型属性的继承,构造函数实现实例属性的继承 每创建一个实例都会调用一次Super.call(),每个实例都创建自己的实例属性,引用类型属性在实例之间也不共享