??前前后后已經快寫了2年左右javaScript,剛開始只是簡單用于一些表單驗證和操作dom節點,并沒有深入的使用,隨著漸漸的深入,開始不想去寫重復的代碼(懶的開始),從而寫簡單的繼承,封裝,抽象等等,最終效果寫重復代碼少、可用性高(主要:迭代快、代碼可以持續使用,加班也少)
Demo構造函數聲明類
function Person(name){
this.name = name;
}
new生成實例
new生成實例的缺點:無法共享屬性和方法,每次new新的實例會開辟新的內存空間,造成極大的資源浪費。
var personA = new Person('小明');
console.log(personA.name);
構造函數的this指向新的實例
如:
function Person(name){
this.name = name;
this.sex = '女'
}
var personA = new Person('小明');
var personB = new Person('小妞');
personA.sex = '男';
console.log(personB.sex); //女
在這里我們該采用聲明解決方案呢?設計者很好的解決了這個問題,那么就是prototype屬性(包含對象)的引入
prototype屬性
它的好處是,實例一旦創建,將自動共同持有共享屬性和方法,如:
function Person(name){
this.name = name;
}
Person.prototype.sex = '女';
var personA = new Person('小明');
var personB = new Person('小妞');
console.log(personA.sex); //女
console.log(personB.sex); //女
//證明它們是共享的
Person.prototype.sex = '男';
console.log(personA.sex); //男
console.log(personB.sex); //男
也許在這里你看不出prototype的好處,但是當你有很多方法和屬性時,你的運行效率還高嘛?那么:
function Person(name, sex){
this.name = name;
this.sex = sex,
this.country = '中國',
this.show = function(){
console.log(this.name + '的國籍是:'+this.country+',性別:'+this.sex);
}
}
var personA = new Person('小明'.'男');
personA.show(); //小明的國籍是是中國,性別:男
var personB = new Person('小妞','女');
personB.show(); //小妞的國籍是是中國,性別:女
感覺似乎沒有什么問題,但是personA和personB都包含有country、show屬性方法一模一樣的內容,這樣就造成了空間的浪費,效率也降低了,那么我們可以它們共享屬性和方法
function Person(name, sex){
this.name = name;
this.sex = sex,
}
Person.prototype.country = '中國';
Person.prototype.show = function(){
console.log(this.name + '的國籍是:'+this.country+',性別:'+this.sex);
}
var personA = new Person('小明'.'男');
var personB = new Person('小妞','女');
personA.show(); //小明的國籍是是中國,性別:男
personB.show(); //小妞的國籍是是中國,性別:女
配合protorype使用的屬性--isPrototypeOf(),hasOwnPrototype(),in
function Person(name, sex){
this.name = name;
this.sex = sex,
}
Person.prototype.country = '中國';
Person.prototype.show = function(){
console.log(this.name + '的國籍是:'+this.country+',性別:'+this.sex);
}
//isPrototypeOf() 判斷實例和對象之間的關系
console.log(Person.prototype.isPrototype(personA)) //true
console.log(Person.prototype.isPrototype(personB)) //true
//hasOwnPrototype() 判斷屬性是本地屬性,還是繼承自prototype屬性
console.log(personA.hasOwnPrototy('name')) //true
console.log(personA.hasOwnPrototy('country')) //false
//in 判斷是否含有屬性,不管本地還是繼承prototype
console.log('name' in personA) //true
console.log('country' in personA) //true
constructor屬性
繼續使用前面Person原型對象
function Person(name){
this.name = name;
}
Person.prototype.sex = '女';
var personA = new Person('小明');
var personB = new Person('小妞');
//新增的實例自動包含有constructor屬性
console.log(personA.constructor == Person); //true
console.log(personB.constructor == Person); //true
這里也可以使用instanceof判斷實例和原型對象之間的關系
console.log(personA instanceof Person); //true
console.log(personB instanceof Person); //true
常用Object之間“繼承”(構造函數繼承)(5種)
假設現在有Person和Teacher兩個Object,想讓Teacher繼承Person
//Person對象
function Person(name){
this.name = name;
}
//Teacher對象
function Teacher(age,sex){
this.age = age;
this.sex = sex;
}
1、:利用構造函數綁定(call或者apply)
function Teacher(age,sex,name){
Person.apply(this,name);//Person.call(this,name);
this.age = age;
this.sex =sex;
}
2、:使用prototype,也就是我們前面說prototype屬性,修改constructor指向
Teacher.prototype = new Person('xiaoming'); //修改prototy對象原先的值
Teacher.prototype.constructor = Teacher;
var teacher1 = new Teacher(19,'女');
3、:直接繼承prototype
function Person(){}
person.prototype.name = "xiaoming";
function Teacher(age,sex){
this.age = age;
this.sex = sex;
}
//Teacher的prototype對象直接指向Person的prototype對象
Teacher.prototype = Person.prototype;
Teacher.prototype.constructor = Teacher
var teacher1 = new Teacher(19,"女");
4、中介new function(){}空對象
var Fn = new function(){};
Fn.prototype = Person.prototype;
Teacher.prototype = new Fn();
Teacher.prototype.constructor = Teacher;
//擴展封裝
function Extend(ChildObj,ParentObj){
var Fn = new function(){};
Fn.prototype = ParentObj.prototype;
ChildObj.prototype = new Fn();
ChildObj.prototype.constructor = ChildObj;
ChildObj.uber = ParentObj.prototype; //直接指向父對象prototype屬性
}
//Teacher繼承Person
Extend(Teacher,Person);
var teacher1 = new Teacher(19,'女');
5、拷貝繼承(完全)
function Extend(ChildObj, ParentObj) {
var p = ParentObj.prototype;
var c = ChildObj.prototype;
for (var i in p) {
c[i] = p[i];
}
c.uber = p;
}
//Teacher繼承Person
Extend(Teacher,Person);
var teacher1 = new Teacher(19,'女');
非構造函數“繼承”(3種)
//原始
var Person = {
name: '小明'
}
var Teacher ={
age:19,
sex:'女'
}
這里我們如何可以讓Teacher繼承Person
1、:object方法
function object(obj){
function Fn(){}
Fn.prototype = obj;
return new Fn();
}
var teacher1 = object(Person);
teacher1.age = 19;
teacher1.sex = '女';
2、:淺拷貝方法
function extendCopy(ParentObj){
var c = {};
for(var i in ParentObj){
c[i] = p[i];
}
c.uber = p;
return c;
}
//使用extendCopy
var teacher1 = extendCopy(Person);
teacher1.age = 19;
teacher1.sex = '女';
3、:深拷貝方法
function extendDeepCopy(ParentObj,ChildObj){
var ChildObj = ChildObj || {};
for(var i in ParentObj){
if(typeof ParentObj[i] === 'object'){
c[i] = (ParentObj[i].constructor === Array) ? [] : {};
extendDeepCopy(ChildObj[i],ParentObj[i]);
}else{
ChildObj[i] = ParentObj[i];
}
}
return ChildObj;
}
//使用
var teacher1 = extendDeepCopy(Person1);
teacher1.age = 19;
teacher1.sex = '女';
本文版權歸作者共有,歡迎轉載,須保留此段聲明,并給出原文鏈接,謝謝!