js的面向物件總結
之前看過js高程3,但又有些忘計了,想想我以前寫的js程式碼全是過程化,確實要換一種程式設計風格了。
大多數程式語言如php,java,c#,ts的面向物件都是
類->例項
但js卻不是這樣,js不區分類和例項,或者可以說js沒有這種類的這種概念,只是通過原型來模擬一種面向物件程式設計。
在通過原型實現面向物件之前,要了解一個屬性,_proto__,所有物件都會在其內部初始化一個屬性,就是proto,當我們訪問一個物件的屬性時,如果這個物件內部不存在這個屬性,那麼他就會去proto裡找這個屬性,當然proto本身也一個物件 ,所有如果屬性還找到就會繼續找,直到找到object物件。
一、直接確定proto
var Person={
name:'zcj',
height:1.2,
code:function(){
console.log(this.name+"is code js");
}
}
var zcj={
name:'zcj'
}
zcj.__proto__=Person;
zcj.code()
上例程式碼原型鏈如下,具體也可以想像成zcj.code屬性查詢鏈條(根據這個規則一級一級往上找直到找到object這就叫原型鏈)。
zcj->zcj.__proto__(Person)->Person.__proto__(Object.prototype) ->Object.prototype.__proto__(null)
驗證一下
//結果為null
console.log(zcj.__proto__.__proto__.__proto__)
首先來看一張原型神圖
二、通過new關鍵字來確定proto屬性
不寫new,這就是一個普通函式,它返回undefined。但是,如果寫了new,返回當前方法體內的this,也就是說,不需要在最後寫return this,並且這個this的proto屬性指向的是建構函式的prototype屬性,
1.不寫return返回的是Person函式體內的this,寫了return返回return之前的this,如下所示加了return返回的this少了hello屬性
function Person(name){
this.name=name;
this.obj={};
//return 'hhhh'
this.hello=function(){
console.log('Hello,'+this.name+'!')
}
}
var zcj=new Person('zcj');
console.log(zcj);
console.log(zjc.__proto__);
最好把屬性和方法放到Person.prototype中,如果我們通過new Person()建立了很多物件,這些物件的hello函式實際上只需要共享同一個函式就可以了,這樣可以節省很多記憶體。
function Person(name){
this.name=name;
this.obj={};
//return 'hhhh'
}
Person.prototype.hello=function(){
console.log('Hello,'+this.name+'!')
}
var zcj=new Person('zcj');
console.log(zcj);
利用js的原型來實現類的繼承特性
function Student(proto){
this.name=proto.name||'unNamed';
}
function PrimaryStudent(proto){
//呼叫student函式把被呼叫函式的this等於呼叫函式體的this
Student.call(this,proto)
this.grade=proto.grade||1;
}
function F(){
}
F.prototype=Student.prototype;
PrimaryStudent.prototype=new F();
//強加一個constuctor屬性指向primarystudent
PrimaryStudent.prototype.constructor=PrimaryStudent
PrimaryStudent.prototype.getGride=function(){
return this.grade;
}
var zcj=new PrimaryStudent({
name:'小明',
grade:2
});
console.log(zcj)
zcj物件的原型鏈
zcj.__proto__(Primarystudent.prototype)->Primarystudent.prototype.__proto__(F.prototype(Student.prototype))->F.prototype(Student.prototype).__proto__->Object.prototype.__proto->null
嗯,很麻煩是吧,好了大神都知道了,es6己經支援class關鍵字了啊,利用es6的class來實現,ES6引入的class和原有的JavaScript原型繼承有什麼區別呢?實際上它們沒有任何區別,class的作用就是讓JavaScript引擎去實現原來需要我們自己編寫的原型鏈程式碼。簡而言之,用class的好處就是極大地簡化了原型鏈程式碼,google是支援的,其他瀏覽器不支援的話就可以用一些編譯工具,如babel