核心提示:JS面向对象:这种模式的缺点是无法识别实例是属于哪一个对象。function createPerson(name,age,place){ var obj = {}; obj.name=name; ob...
JS面向对象:这种模式的缺点是无法识别实例是属于哪一个对象。
function createPerson(name,age,place){ var obj = {}; obj.name=name; obj.age=age; obj.place=place; obj.getName= function(){ console.log('该对象的名字是'+this.name) }; return obj; } //工厂模式对象创建方式,与寄生构造函数模式作比较 var person1 = createPerson('lucy','23','swu');
构造函数模式
这种模式的优点是可以识别构造函数模式,他的优点是可以识别实例是属于哪一个对象,缺点是无法实现某些函数的共用,即每个方法都要在都要在实例上创建一遍
function Person(name,age,place) { this.name = name; this.age = age; this.place = place; this.getName = function () { console.log('Name: '+this.name); } } var person = new Person('lucy',23,'西南大学'); //Name:lucy person.getName(); //true console.log(person instanceof Person);
原型模式
每个函数都有一个prototype属性,这个属性指向这个函数的原型对象,同时每个原型都有一个constructor属性,指向该函数,每个函数的实例都有一个默认的proto属性指向该原型对象,原型的意思有点类似与Java中的静态变量,在内存中分配出一块空间,多个实例共享这个空间。
function person() { } person.prototype.name='lucy'; person.prototype.age=23; person.prototype.place="西南大学"; var p1 = new person(); var p2 = new person(); //lucy console.log(p1.name); p1.name='kathy'; //kathy console.log(p1.name); //lucy console.log(p2.name); //false alert(p1.name===p2.name);
原型链查找对象
先在该实例中查找有没有这个属性,如果有,就执行,不会再向上一级查找,如果没有找到,就去该实例的原型对象中去寻找。 isPrototypeOf()用来判断某个属性是否是该实例有一个指向原型对象的指针。hasOwnProperty()用来判断某个属性是否是某个实例的实例属性。
function person() { } person.prototype.name='lucy'; person.prototype.age=23; person.prototype.place="西南大学"; var p1 = new person(); p1.name='kathy'; //true alert(person.prototype.isPrototypeOf(p1)); //true alert(p1.hasOwnProperty('name')); function judge(sx,object) { if ( sx in object && !object.hasOwnProperty(sx)){ alert(true); } else { alert(false); } } //false judge('name',p1);
原型模式的缺点是无法个性,就是如果一组属性你不想共有,单独使用原型模式是无法实现的。
一种更简单的原型模式,这种模式的特点是会重写整个原型对象,constructor会指向Object而不是该对象。
Person.prototype={ constructor:Person, //1 name:'Lucy', age:23, place:'swu', getName:function () { alert(this.name); } }; var person = new Person(); //true //将1注释之后输出为false; alert(person.constructor===Person);
组合使用构造函数模式和原型模式
这种方式可以将构造函数模式和原型模式的优点结合起来,既能实现函数的复用,又可以自定义属性。
function Person(name,age,job) { this.name=name; this.age=age; this.job=job; this.films = ['1','2','3']; } Person.prototype={ constructor:Person, getName:function () { alert(this.name); } };
动态原型模式
这种模式能很好的封装信息,又可以避免多次重写原,注意这里不可以使用字面量的方式创建原型,因为这会切断,实例与新原型之间的联系。
function Person(name,age,job) { this.name=name; this.age=age; this.job=job; this.films = ['1','2','3']; if (typeof this.getName != 'function'){ Person.prototype.getName = function(){ alert(this.name); } } }
寄生构造函数模式
这种模式基本上与工厂模式一样, 只是在创建对象的时候有一点区别
function Person(name,age,place){ var obj = {}; obj.name=name; obj.age=age; obj.place=place; obj.getName= function(){ console.log('该对象的名字是'+this.name) }; return obj; } //工厂模式对象创建方式,与寄生构造函数模式作比较 var person1 =new Person('lucy','23','swu'); person1.getName();
稳妥构造函数模式
function Person(name,age,job){ var o = new Object(); o.sayname = function(){ alert(name); }; return o; }
继承
原型链继承
使子对象的原型对象指向父对象的一个实例 子对象的原型对象拥有父对象的所有实例属性,但是也可以访问到父对象的原型方法,以及原型属性,因为此时,子对象的原型对象也指向了父对象的原型对象原型链继承的搜索方式,先在实例中寻找,然后到子对象的原型对象中寻找,然后到父对象的原型对象中去寻找。
function Parent() { this.name = 'yige'; this.age = 17; this.place = 'swu'; } Parent.prototype.getName=function () { alert(this.name); }; function Sub() { } Sub.prototype = new Parent(); //yige alert(Sub.prototype.name);
借用构造函数
也就是冒充函数的方法,使用 apply 或者 call 方法
function Parent(name){ this.name = name; } function Sub(){ Parent.call(this,'lucy') } var sub1 = new Sun(); //'lucy' alert(sub1.name);
组合继承
不需要共用的属性使用构造函数继承,需要共用的属性和方法使用原型链继承,这也是最常用的一种继承方式。原型式继承
基本思想是父对象直接赋值给新对象的原型,新的实例属性各自定义,引用类型公有。
function object(o){ function F(){} F.prototype = o; return new F(); } var person ={ name: 'kathy', friends: ['1','2','3'] } var person1 = object(Person);
寄生式继承
基本思路是类似于工厂模式,创建一个函数,这个函数返回一个对象,然后调用这个函数中的方法。寄生组合式继承
function inPtototype(subType,superType){ var prototype =object(superType.prototype); prototype.constructor = subType; subType.prototype = prototype; }