老生常談javascript的面向?qū)ο笏枷?/h1>
更新時(shí)間:2017年08月22日 08:29:51 投稿:jingxian
下面小編就為大家?guī)?lái)一篇老生常談javascript的面向?qū)ο笏枷?。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
面向?qū)ο蟮娜蠡咎匦?/strong>
封裝(把相關(guān)的信息(無(wú)論數(shù)據(jù)或方法)存儲(chǔ)在對(duì)象中的能力)
繼承(由另一個(gè)類(lèi)(或多個(gè)類(lèi))得來(lái)類(lèi)的屬性和方法的能力)
多態(tài)(一個(gè)對(duì)象在不同情況下的多種形態(tài))
定義類(lèi)或?qū)ο?/strong>
第一種:基于Object對(duì)象
var person = new Object();
person.name = "Rose";
person.age = 18;
person.getName = function () {
return this.name;
};
console.log(person.name);//Rose
console.log(person.getName);//function () {return this.name;}
console.log(person.getName());//Rose
缺點(diǎn):不能創(chuàng)建多個(gè)對(duì)象。
第二種:基于字面量方式
var person = {
name : "Rose",
age : 18 ,
getName : function () {
return this.name;
}
};
console.log(person.name);//Rose
console.log(person.getName);//function () {return this.name;}
console.log(person.getName());//Rose
優(yōu)點(diǎn):比較清楚的查找對(duì)象包含的屬性和方法;
缺點(diǎn):不能創(chuàng)建多個(gè)對(duì)象。
第三種:工廠(chǎng)模式
方式一:
function createPerson(name,age) {
var object = new Object();
object.name = name;
object.age = age;
object.getName = function () {
return this.name;
};
return object;
}
var person1 = createPerson("Rose",18);
var person2 = createPerson("Jack",20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName);//false//重復(fù)生成函數(shù),為每個(gè)對(duì)象都創(chuàng)建獨(dú)立的函數(shù)版本
優(yōu)點(diǎn):可以創(chuàng)建多個(gè)對(duì)象;
缺點(diǎn):重復(fù)生成函數(shù)getName(),為每個(gè)對(duì)象都創(chuàng)建獨(dú)立的函數(shù)版本。
方式二:
function createPerson(name,age) {
var object = new Object();
object.name = name;
object.age = age;
object.getName = getName;
return object;
}
function getName() {
return this.name;
}
var person1 = createPerson("Rose",18);
var person2 = createPerson("Jack",20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName);//true//共享同一個(gè)函數(shù)
優(yōu)點(diǎn):可以創(chuàng)建多個(gè)對(duì)象;
缺點(diǎn):從語(yǔ)義上講,函數(shù)getName()不太像是Person對(duì)象的方法,辨識(shí)度不高。
第四種:構(gòu)造函數(shù)方式
方式一:
function Person(name,age) {
this.name = name;
this.age = age;
this.getName = function () {
return this.name;
}
}
var person1 = new Person("Rose",18);
var person2 = new Person("Jack",20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName); //false//重復(fù)生成函數(shù),為每個(gè)對(duì)象都創(chuàng)建獨(dú)立的函數(shù)版本
優(yōu)點(diǎn):可以創(chuàng)建多個(gè)對(duì)象;
缺點(diǎn):重復(fù)生成函數(shù)getName(),為每個(gè)對(duì)象都創(chuàng)建獨(dú)立的函數(shù)版本。
方式二:
function Person(name,age) {
this.name = name;
this.age = age;
this.getName = getName ;
}
function getName() {
return this.name;
}
var person1 = new Person("Rose",18);
var person2 = new Person("Jack",20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName); //true//共享同一個(gè)函數(shù)
優(yōu)點(diǎn):可以創(chuàng)建多個(gè)對(duì)象;
缺點(diǎn):從語(yǔ)義上講,函數(shù)getName()不太像是Person對(duì)象的方法,辨識(shí)度不高。
第五種:原型方式
function Person() {
}
Person.prototype.name = 'Rose';
Person.prototype.age = 18;
Person.prototype.getName = function () {
return this.name;
};
var person1 = new Person();
var person2 = new Person();
console.log(person1.name);//Rose
console.log(person2.name);//Rose//共享同一個(gè)屬性
console.log(person1.getName === person2.getName);//true//共享同一個(gè)函數(shù)
缺點(diǎn):它省略了為構(gòu)造函數(shù)傳遞初始化參數(shù),這在一定程序帶來(lái)不便;另外,最主要是當(dāng)對(duì)象的屬性是引用類(lèi)型時(shí),它的值是不變的,總是引用同一個(gè)外部對(duì)象,所有實(shí)例對(duì)該對(duì)象的操作都會(huì)影響其它實(shí)例:
function Person() {
}
Person.prototype.name = 'Rose';
Person.prototype.age = 18;
Person.prototype.lessons = ["語(yǔ)文","數(shù)學(xué)"];
Person.prototype.getName = function () {
return this.name;
};
var person1 = new Person();
person1.lessons.push("英語(yǔ)");
var person2 = new Person();
console.log(person1.lessons);//["語(yǔ)文", "數(shù)學(xué)", "英語(yǔ)"]
console.log(person2.lessons);//["語(yǔ)文", "數(shù)學(xué)", "英語(yǔ)"]//person1修改影響了person2
第六種:構(gòu)造函數(shù)+原型方式(推薦)
function Person(name,age) {
this.name = name;
this.age = age;
}
Person.prototype.getName = function () {
return this.name;
};
var person1 = new Person('Rose', 18);
var person2 = new Person('Jack', 20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName);//true//共享原型中定義的方法
缺點(diǎn):屬性定義在構(gòu)造函數(shù)內(nèi),方法定義在構(gòu)造函數(shù)外,與面向?qū)ο蟮姆庋b思想不符。
第七種:構(gòu)造函數(shù)+動(dòng)態(tài)原型方式(推薦)
方式一:
function Person(name,age) {
this.name = name;
this.age = age;
if (typeof Person._getName === "undefined"){
Person.prototype.getName = function () {
return this.name;
};
Person._getName = true;
}
}
var person1 = new Person('Rose', 18);
var person2 = new Person('Jack', 20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName);//true//共享原型中定義的方法
方式二:
function Person(name,age) {
this.name = name;
this.age = age;
if (typeof this.getName !== "function"){
Person.prototype.getName = function () {
return this.name;
};
}
}
var person1 = new Person('Rose', 18);
var person2 = new Person('Jack', 20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName);//true//共享原型中定義的方法
對(duì)象屬性的擴(kuò)展及刪除
Javascript的對(duì)象可以使用 '.' 操作符動(dòng)態(tài)的擴(kuò)展其屬性,可以使用 'delete' 關(guān)鍵字或?qū)傩缘闹翟O(shè)置為 'undefined' 來(lái)刪除屬性。
function Person(name,age) {
this.name = name;
this.age = age;
if (typeof Person._getName === "undefined"){
Person.prototype.getName = function () {
return this.name;
};
Person._getName = true;
}
}
var person = new Person("Rose",18);
person.job = 'Engineer';//添加屬性
console.log(person.job);//Engineer
delete person.job;//刪除屬性
console.log(person.job);//undefined//刪除屬性后值為undefined
person.age = undefined;//刪除屬性
console.log(person.age);//undefined//刪除屬性后值為undefined
對(duì)象屬性類(lèi)型
數(shù)據(jù)屬性
特性:
[configurable]:表示能否使用delete操作符刪除從而重新定義,或能否修改為訪(fǎng)問(wèn)器屬性。默認(rèn)為true;
[enumberable]:表示是否可通過(guò)for-in循環(huán)返回屬性。默認(rèn)true;
[writable]:表示是否可修改屬性的值。默認(rèn)true;
[value]:包含該屬性的數(shù)據(jù)值。讀取/寫(xiě)入都是該值。默認(rèn)為undefined;如上面實(shí)例對(duì)象person中定義了name屬性,其值為'My name',對(duì)該值的修改都反正在這個(gè)位置
function Person(name,age) {
this.name = name;
this.age = age;
if (typeof Person._getName === "undefined"){
Person.prototype.getName = function () {
return this.name;
};
Person._getName = true;
}
}
var person = new Person("Rose",18);
Object.defineProperty(person,"name",{configurable:false,writable:false});
person.name = "Jack";
console.log(person.name);//Rose//重新賦值無(wú)效
delete person.name;
console.log(person.name);//Rose//刪除無(wú)效
注意:
一旦將configurable設(shè)置為false,則無(wú)法再使用defineProperty將其修改為true(執(zhí)行會(huì)報(bào)錯(cuò):cannot redefine property : propertyName)
function Person(name,age) {
this.name = name;
this.age = age;
if (typeof Person._getName === "undefined"){
Person.prototype.getName = function () {
return this.name;
};
Person._getName = true;
}
}
var person = new Person("Rose",18);
Object.defineProperty(person,"name",{configurable:false,writable:false});
person.name = "Jack";
console.log(person.name);//Rose//重新賦值無(wú)效
delete person.name;
console.log(person.name);//Rose//刪除無(wú)效
Object.defineProperty(person,"name",{configurable:true,writable:true});//Cannot redefine property: name
訪(fǎng)問(wèn)器屬性
特性:
[configurable]:是否可通過(guò)delete操作符刪除重新定義屬性;
[numberable]:是否可通過(guò)for-in循環(huán)查找該屬性;
[get]:讀取屬性時(shí)調(diào)用,默認(rèn):undefined;
[set]:寫(xiě)入屬性時(shí)調(diào)用,默認(rèn):undefined;
訪(fǎng)問(wèn)器屬性不能直接定義,必須使用defineProperty()或defineProperties來(lái)定義:如下
function Person(name,age) {
this.name = name;
this._age = age;
if (typeof Person._getName === "undefined"){
Person.prototype.getName = function () {
return this.name;
};
Person._getName = true;
}
}
var person = new Person("Rose",18);
Object.defineProperty(person,"age",{
get:function () {
return this._age;
},
set:function (age) {
this._age = age;
}});
person.age = 20;
console.log(person.age);//20//person.age=20是使用set方法將20賦值給_age,person.age是使用get方法將_age的讀取出來(lái)
console.log(person._age);//20
獲取所有的屬性和屬性的特性
使用Object.getOwnPropertyNames(object)方法可以獲取所有的屬性;
使用Object.getOwnPropertyDescriptor(object,property)方法可以取得給定屬性的特性;
function Person(name,age) {
this.name = name;
this._age = age;
if (typeof Person._getName === "undefined"){
Person.prototype.getName = function () {
return this.name;
};
Person._getName = true;
}
}
var person = new Person("Rose",18);
Object.defineProperty(person,"age",{
get:function () {
return this._age;
},
set:function (age) {
this._age = age;
}});
console.log(Object.getOwnPropertyNames(person));//["name", "_age", "age"]
console.log(Object.getOwnPropertyDescriptor(person,"age"));//{enumerable: false, configurable: false, get: function, set: function}
對(duì)于數(shù)據(jù)屬性,可以取得:configurable,enumberable,writable和value;
對(duì)于訪(fǎng)問(wèn)器屬性,可以取得:configurable,enumberable,get和set;
繼承機(jī)制實(shí)現(xiàn)
對(duì)象冒充
function Father(name) {
this.name = name ;
this.getName = function () {
return this.name;
}
}
function Son(name,age) {
this._newMethod = Father;
this._newMethod(name);
delete this._newMethod;
this.age = age;
this.getAge = function () {
return this.age;
}
}
var father = new Father("Tom");
var son = new Son("Jack",18);
console.log(father.getName());//Tom
console.log(son.getName());//Jack//繼承父類(lèi)getName()方法
console.log(son.getAge());//18
多繼承(利用對(duì)象冒充可以實(shí)現(xiàn)多繼承)
function FatherA(name) {
this.name = name ;
this.getName = function () {
return this.name;
}
}
function FatherB(job) {
this.job = job;
this.getJob = function () {
return this.job;
}
}
function Son(name,job,age) {
this._newMethod = FatherA;
this._newMethod(name);
delete this._newMethod;
this._newMethod = FatherB;
this._newMethod(job);
delete this._newMethod;
this.age = age;
this.getAge = function () {
return this.age;
}
}
var fatherA = new FatherA("Tom");
var fatherB = new FatherB("Engineer");
var son = new Son("Jack","Programmer",18);
console.log(fatherA.getName());//Tom
console.log(fatherB.getJob());//Engineer
console.log(son.getName());//Jack//繼承父類(lèi)FatherA的getName()方法
console.log(son.getJob());//Programmer//繼承父類(lèi)FatherB的getJob()方法
console.log(son.getAge());//18
call()方法
function Father(name) {
this.name = name ;
this.getName = function () {
return this.name;
}
}
function Son(name,job,age) {
Father.call(this,name);
this.age = age;
this.getAge = function () {
return this.age;
}
}
var father = new Father("Tom");
var son = new Son("Jack","Programmer",18);
console.log(father.getName());//Tom
console.log(son.getName());//Jack//繼承父類(lèi)getName()方法
console.log(son.getAge());//18
多繼承(利用call()方法實(shí)現(xiàn)多繼承)
function FatherA(name) {
this.name = name ;
this.getName = function () {
return this.name;
}
}
function FatherB(job) {
this.job = job;
this.getJob = function () {
return this.job;
}
}
function Son(name,job,age) {
FatherA.call(this,name);
FatherB.call(this,job);
this.age = age;
this.getAge = function () {
return this.age;
}
}
var fatherA = new FatherA("Tom");
var fatherB = new FatherB("Engineer");
var son = new Son("Jack","Programmer",18);
console.log(fatherA.getName());//Tom
console.log(fatherB.getJob());//Engineer
console.log(son.getName());//Jack//繼承父類(lèi)FatherA的getName()方法
console.log(son.getJob());//Programmer//繼承父類(lèi)FatherB的getJob()方法
console.log(son.getAge());//18
apply()方法
function Father(name) {
this.name = name ;
this.getName = function () {
return this.name;
}
}
function Son(name,job,age) {
Father.apply(this,new Array(name));
this.age = age;
this.getAge = function () {
return this.age;
}
}
var father = new Father("Tom");
var son = new Son("Jack","Programmer",18);
console.log(father.getName());//Tom
console.log(son.getName());//Jack//繼承父類(lèi)getName()方法
console.log(son.getAge());//18
多繼承(利用apply()方法實(shí)現(xiàn)多繼承)
function FatherA(name) {
this.name = name ;
this.getName = function () {
return this.name;
}
}
function FatherB(job) {
this.job = job;
this.getJob = function () {
return this.job;
}
}
function Son(name,job,age) {
FatherA.apply(this,new Array(name));
FatherB.apply(this,new Array(job));
this.age = age;
this.getAge = function () {
return this.age;
}
}
var fatherA = new FatherA("Tom");
var fatherB = new FatherB("Engineer");
var son = new Son("Jack","Programmer",18);
console.log(fatherA.getName());//Tom
console.log(fatherB.getJob());//Engineer
console.log(son.getName());//Jack//繼承父類(lèi)FatherA的getName()方法
console.log(son.getJob());//Programmer//繼承父類(lèi)FatherB的getJob()方法
console.log(son.getAge());//18
原型鏈方法
function Father() {
}
Father.prototype.name = "Tom";
Father.prototype.getName = function () {
return this.name;
};
function Son() {
}
Son.prototype = new Father();
Son.prototype.age = 18;
Son.prototype.getAge = function () {
return this.age;
};
var father = new Father();
var son = new Son();
console.log(father.getName());//Tom
console.log(son.getName());//Tom//繼承父類(lèi)FatherA的getName()方法
console.log(son.getAge());//18
混合方式(call()+原型鏈)
function Father(name) {
this.name = name;
}
Father.prototype.getName = function () {
return this.name;
};
function Son(name,age) {
Father.call(this,name);
this.age = age;
}
Son.prototype = new Father();
Son.prototype.getAge = function () {
return this.age;
};
var father = new Father("Tom");
var son = new Son("Jack",18);
console.log(father.getName());//Tom
console.log(son.getName());//Jack//繼承父類(lèi)Father的getName()方法
console.log(son.getAge());//18
多態(tài)機(jī)制實(shí)現(xiàn)
function Person(name) {
this.name = name;
if (typeof this.getName !== "function"){
Person.prototype.getName = function () {
return this.name;
}
}
if (typeof this.toEat !== "function"){
Person.prototype.toEat = function (animal) {
console.log( this.getName() + "說(shuō)去吃飯:");
animal.eat();
}
}
}
function Animal(name) {
this.name = name;
if (typeof this.getName !== "function"){
Animal.prototype.getName = function () {
return this.name;
}
}
}
function Cat(name) {
Animal.call(this,name);
if (typeof this.eat !== "function"){
Cat.prototype.eat = function () {
console.log(this.getName() + "吃魚(yú)");
}
}
}
Cat.prototype = new Animal();
function Dog(name) {
Animal.call(this,name);
if (typeof this.eat !== "function"){
Dog.prototype.eat = function () {
console.log(this.getName() + "啃骨頭");
}
}
}
Dog.prototype = new Animal();
var person = new Person("Tom");
person.toEat(new Cat("cat"));//Tom說(shuō)去吃飯:cat吃魚(yú)
person.toEat(new Dog("dog"));//Tom說(shuō)去吃飯:dog啃骨頭
以上這篇老生常談javascript的面向?qū)ο笏枷刖褪切【幏窒斫o大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
-
如何實(shí)現(xiàn)一個(gè)webpack模塊解析器
這篇文章主要介紹了如何實(shí)現(xiàn)一個(gè)webpack模塊解析器,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧 2018-10-10
-
js屬性對(duì)象的hasOwnProperty方法的使用
這篇文章主要介紹了js屬性對(duì)象的hasOwnProperty方法的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧 2021-02-02
-
layui使用及簡(jiǎn)單的三級(jí)聯(lián)動(dòng)實(shí)現(xiàn)教程
這篇文章主要給大家介紹了關(guān)于layui使用及簡(jiǎn)單的三級(jí)聯(lián)動(dòng)的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧 2020-12-12
-
next.js?getServerSideProps源碼解析
這篇文章主要為大家介紹了next.js?getServerSideProps源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪 2022-10-10
-
javascript DOM 操作基礎(chǔ)知識(shí)小結(jié)
經(jīng)常用到j(luò)avascript對(duì)dom,喜歡這方便的朋友也很多,要想更好的對(duì)dom進(jìn)行操作,這些基礎(chǔ)一定要知道的。 2010-04-04
-
利用JavaScript實(shí)現(xiàn)一個(gè)日期范圍選擇器
日期范圍選擇器是一個(gè)常見(jiàn)的Web應(yīng)用功能,它允許用戶(hù)選擇一個(gè)日期范圍,本文我們將使用JavaScript來(lái)實(shí)現(xiàn)這個(gè)功能,感興趣的小伙伴可以了解下 2024-01-01
最新評(píng)論
面向?qū)ο蟮娜蠡咎匦?/strong>
封裝(把相關(guān)的信息(無(wú)論數(shù)據(jù)或方法)存儲(chǔ)在對(duì)象中的能力)
繼承(由另一個(gè)類(lèi)(或多個(gè)類(lèi))得來(lái)類(lèi)的屬性和方法的能力)
多態(tài)(一個(gè)對(duì)象在不同情況下的多種形態(tài))
定義類(lèi)或?qū)ο?/strong>
第一種:基于Object對(duì)象
var person = new Object(); person.name = "Rose"; person.age = 18; person.getName = function () { return this.name; }; console.log(person.name);//Rose console.log(person.getName);//function () {return this.name;} console.log(person.getName());//Rose
缺點(diǎn):不能創(chuàng)建多個(gè)對(duì)象。
第二種:基于字面量方式
var person = { name : "Rose", age : 18 , getName : function () { return this.name; } }; console.log(person.name);//Rose console.log(person.getName);//function () {return this.name;} console.log(person.getName());//Rose
優(yōu)點(diǎn):比較清楚的查找對(duì)象包含的屬性和方法;
缺點(diǎn):不能創(chuàng)建多個(gè)對(duì)象。
第三種:工廠(chǎng)模式
方式一:
function createPerson(name,age) { var object = new Object(); object.name = name; object.age = age; object.getName = function () { return this.name; }; return object; } var person1 = createPerson("Rose",18); var person2 = createPerson("Jack",20); console.log(person1.name);//Rose console.log(person2.name);//Jack console.log(person1.getName === person2.getName);//false//重復(fù)生成函數(shù),為每個(gè)對(duì)象都創(chuàng)建獨(dú)立的函數(shù)版本
優(yōu)點(diǎn):可以創(chuàng)建多個(gè)對(duì)象;
缺點(diǎn):重復(fù)生成函數(shù)getName(),為每個(gè)對(duì)象都創(chuàng)建獨(dú)立的函數(shù)版本。
方式二:
function createPerson(name,age) { var object = new Object(); object.name = name; object.age = age; object.getName = getName; return object; } function getName() { return this.name; } var person1 = createPerson("Rose",18); var person2 = createPerson("Jack",20); console.log(person1.name);//Rose console.log(person2.name);//Jack console.log(person1.getName === person2.getName);//true//共享同一個(gè)函數(shù)
優(yōu)點(diǎn):可以創(chuàng)建多個(gè)對(duì)象;
缺點(diǎn):從語(yǔ)義上講,函數(shù)getName()不太像是Person對(duì)象的方法,辨識(shí)度不高。
第四種:構(gòu)造函數(shù)方式
方式一:
function Person(name,age) { this.name = name; this.age = age; this.getName = function () { return this.name; } } var person1 = new Person("Rose",18); var person2 = new Person("Jack",20); console.log(person1.name);//Rose console.log(person2.name);//Jack console.log(person1.getName === person2.getName); //false//重復(fù)生成函數(shù),為每個(gè)對(duì)象都創(chuàng)建獨(dú)立的函數(shù)版本
優(yōu)點(diǎn):可以創(chuàng)建多個(gè)對(duì)象;
缺點(diǎn):重復(fù)生成函數(shù)getName(),為每個(gè)對(duì)象都創(chuàng)建獨(dú)立的函數(shù)版本。
方式二:
function Person(name,age) { this.name = name; this.age = age; this.getName = getName ; } function getName() { return this.name; } var person1 = new Person("Rose",18); var person2 = new Person("Jack",20); console.log(person1.name);//Rose console.log(person2.name);//Jack console.log(person1.getName === person2.getName); //true//共享同一個(gè)函數(shù)
優(yōu)點(diǎn):可以創(chuàng)建多個(gè)對(duì)象;
缺點(diǎn):從語(yǔ)義上講,函數(shù)getName()不太像是Person對(duì)象的方法,辨識(shí)度不高。
第五種:原型方式
function Person() { } Person.prototype.name = 'Rose'; Person.prototype.age = 18; Person.prototype.getName = function () { return this.name; }; var person1 = new Person(); var person2 = new Person(); console.log(person1.name);//Rose console.log(person2.name);//Rose//共享同一個(gè)屬性 console.log(person1.getName === person2.getName);//true//共享同一個(gè)函數(shù)
缺點(diǎn):它省略了為構(gòu)造函數(shù)傳遞初始化參數(shù),這在一定程序帶來(lái)不便;另外,最主要是當(dāng)對(duì)象的屬性是引用類(lèi)型時(shí),它的值是不變的,總是引用同一個(gè)外部對(duì)象,所有實(shí)例對(duì)該對(duì)象的操作都會(huì)影響其它實(shí)例:
function Person() { } Person.prototype.name = 'Rose'; Person.prototype.age = 18; Person.prototype.lessons = ["語(yǔ)文","數(shù)學(xué)"]; Person.prototype.getName = function () { return this.name; }; var person1 = new Person(); person1.lessons.push("英語(yǔ)"); var person2 = new Person(); console.log(person1.lessons);//["語(yǔ)文", "數(shù)學(xué)", "英語(yǔ)"] console.log(person2.lessons);//["語(yǔ)文", "數(shù)學(xué)", "英語(yǔ)"]//person1修改影響了person2
第六種:構(gòu)造函數(shù)+原型方式(推薦)
function Person(name,age) { this.name = name; this.age = age; } Person.prototype.getName = function () { return this.name; }; var person1 = new Person('Rose', 18); var person2 = new Person('Jack', 20); console.log(person1.name);//Rose console.log(person2.name);//Jack console.log(person1.getName === person2.getName);//true//共享原型中定義的方法
缺點(diǎn):屬性定義在構(gòu)造函數(shù)內(nèi),方法定義在構(gòu)造函數(shù)外,與面向?qū)ο蟮姆庋b思想不符。
第七種:構(gòu)造函數(shù)+動(dòng)態(tài)原型方式(推薦)
方式一:
function Person(name,age) { this.name = name; this.age = age; if (typeof Person._getName === "undefined"){ Person.prototype.getName = function () { return this.name; }; Person._getName = true; } } var person1 = new Person('Rose', 18); var person2 = new Person('Jack', 20); console.log(person1.name);//Rose console.log(person2.name);//Jack console.log(person1.getName === person2.getName);//true//共享原型中定義的方法
方式二:
function Person(name,age) { this.name = name; this.age = age; if (typeof this.getName !== "function"){ Person.prototype.getName = function () { return this.name; }; } } var person1 = new Person('Rose', 18); var person2 = new Person('Jack', 20); console.log(person1.name);//Rose console.log(person2.name);//Jack console.log(person1.getName === person2.getName);//true//共享原型中定義的方法
對(duì)象屬性的擴(kuò)展及刪除
Javascript的對(duì)象可以使用 '.' 操作符動(dòng)態(tài)的擴(kuò)展其屬性,可以使用 'delete' 關(guān)鍵字或?qū)傩缘闹翟O(shè)置為 'undefined' 來(lái)刪除屬性。
function Person(name,age) { this.name = name; this.age = age; if (typeof Person._getName === "undefined"){ Person.prototype.getName = function () { return this.name; }; Person._getName = true; } } var person = new Person("Rose",18); person.job = 'Engineer';//添加屬性 console.log(person.job);//Engineer delete person.job;//刪除屬性 console.log(person.job);//undefined//刪除屬性后值為undefined person.age = undefined;//刪除屬性 console.log(person.age);//undefined//刪除屬性后值為undefined
對(duì)象屬性類(lèi)型
數(shù)據(jù)屬性
特性:
[configurable]:表示能否使用delete操作符刪除從而重新定義,或能否修改為訪(fǎng)問(wèn)器屬性。默認(rèn)為true;
[enumberable]:表示是否可通過(guò)for-in循環(huán)返回屬性。默認(rèn)true;
[writable]:表示是否可修改屬性的值。默認(rèn)true;
[value]:包含該屬性的數(shù)據(jù)值。讀取/寫(xiě)入都是該值。默認(rèn)為undefined;如上面實(shí)例對(duì)象person中定義了name屬性,其值為'My name',對(duì)該值的修改都反正在這個(gè)位置
function Person(name,age) { this.name = name; this.age = age; if (typeof Person._getName === "undefined"){ Person.prototype.getName = function () { return this.name; }; Person._getName = true; } } var person = new Person("Rose",18); Object.defineProperty(person,"name",{configurable:false,writable:false}); person.name = "Jack"; console.log(person.name);//Rose//重新賦值無(wú)效 delete person.name; console.log(person.name);//Rose//刪除無(wú)效
注意:
一旦將configurable設(shè)置為false,則無(wú)法再使用defineProperty將其修改為true(執(zhí)行會(huì)報(bào)錯(cuò):cannot redefine property : propertyName)
function Person(name,age) { this.name = name; this.age = age; if (typeof Person._getName === "undefined"){ Person.prototype.getName = function () { return this.name; }; Person._getName = true; } } var person = new Person("Rose",18); Object.defineProperty(person,"name",{configurable:false,writable:false}); person.name = "Jack"; console.log(person.name);//Rose//重新賦值無(wú)效 delete person.name; console.log(person.name);//Rose//刪除無(wú)效 Object.defineProperty(person,"name",{configurable:true,writable:true});//Cannot redefine property: name
訪(fǎng)問(wèn)器屬性
特性:
[configurable]:是否可通過(guò)delete操作符刪除重新定義屬性;
[numberable]:是否可通過(guò)for-in循環(huán)查找該屬性;
[get]:讀取屬性時(shí)調(diào)用,默認(rèn):undefined;
[set]:寫(xiě)入屬性時(shí)調(diào)用,默認(rèn):undefined;
訪(fǎng)問(wèn)器屬性不能直接定義,必須使用defineProperty()或defineProperties來(lái)定義:如下
function Person(name,age) { this.name = name; this._age = age; if (typeof Person._getName === "undefined"){ Person.prototype.getName = function () { return this.name; }; Person._getName = true; } } var person = new Person("Rose",18); Object.defineProperty(person,"age",{ get:function () { return this._age; }, set:function (age) { this._age = age; }}); person.age = 20; console.log(person.age);//20//person.age=20是使用set方法將20賦值給_age,person.age是使用get方法將_age的讀取出來(lái) console.log(person._age);//20
獲取所有的屬性和屬性的特性
使用Object.getOwnPropertyNames(object)方法可以獲取所有的屬性;
使用Object.getOwnPropertyDescriptor(object,property)方法可以取得給定屬性的特性;
function Person(name,age) { this.name = name; this._age = age; if (typeof Person._getName === "undefined"){ Person.prototype.getName = function () { return this.name; }; Person._getName = true; } } var person = new Person("Rose",18); Object.defineProperty(person,"age",{ get:function () { return this._age; }, set:function (age) { this._age = age; }}); console.log(Object.getOwnPropertyNames(person));//["name", "_age", "age"] console.log(Object.getOwnPropertyDescriptor(person,"age"));//{enumerable: false, configurable: false, get: function, set: function}
對(duì)于數(shù)據(jù)屬性,可以取得:configurable,enumberable,writable和value;
對(duì)于訪(fǎng)問(wèn)器屬性,可以取得:configurable,enumberable,get和set;
繼承機(jī)制實(shí)現(xiàn)
對(duì)象冒充
function Father(name) { this.name = name ; this.getName = function () { return this.name; } } function Son(name,age) { this._newMethod = Father; this._newMethod(name); delete this._newMethod; this.age = age; this.getAge = function () { return this.age; } } var father = new Father("Tom"); var son = new Son("Jack",18); console.log(father.getName());//Tom console.log(son.getName());//Jack//繼承父類(lèi)getName()方法 console.log(son.getAge());//18
多繼承(利用對(duì)象冒充可以實(shí)現(xiàn)多繼承)
function FatherA(name) { this.name = name ; this.getName = function () { return this.name; } } function FatherB(job) { this.job = job; this.getJob = function () { return this.job; } } function Son(name,job,age) { this._newMethod = FatherA; this._newMethod(name); delete this._newMethod; this._newMethod = FatherB; this._newMethod(job); delete this._newMethod; this.age = age; this.getAge = function () { return this.age; } } var fatherA = new FatherA("Tom"); var fatherB = new FatherB("Engineer"); var son = new Son("Jack","Programmer",18); console.log(fatherA.getName());//Tom console.log(fatherB.getJob());//Engineer console.log(son.getName());//Jack//繼承父類(lèi)FatherA的getName()方法 console.log(son.getJob());//Programmer//繼承父類(lèi)FatherB的getJob()方法 console.log(son.getAge());//18
call()方法
function Father(name) { this.name = name ; this.getName = function () { return this.name; } } function Son(name,job,age) { Father.call(this,name); this.age = age; this.getAge = function () { return this.age; } } var father = new Father("Tom"); var son = new Son("Jack","Programmer",18); console.log(father.getName());//Tom console.log(son.getName());//Jack//繼承父類(lèi)getName()方法 console.log(son.getAge());//18
多繼承(利用call()方法實(shí)現(xiàn)多繼承)
function FatherA(name) { this.name = name ; this.getName = function () { return this.name; } } function FatherB(job) { this.job = job; this.getJob = function () { return this.job; } } function Son(name,job,age) { FatherA.call(this,name); FatherB.call(this,job); this.age = age; this.getAge = function () { return this.age; } } var fatherA = new FatherA("Tom"); var fatherB = new FatherB("Engineer"); var son = new Son("Jack","Programmer",18); console.log(fatherA.getName());//Tom console.log(fatherB.getJob());//Engineer console.log(son.getName());//Jack//繼承父類(lèi)FatherA的getName()方法 console.log(son.getJob());//Programmer//繼承父類(lèi)FatherB的getJob()方法 console.log(son.getAge());//18
apply()方法
function Father(name) { this.name = name ; this.getName = function () { return this.name; } } function Son(name,job,age) { Father.apply(this,new Array(name)); this.age = age; this.getAge = function () { return this.age; } } var father = new Father("Tom"); var son = new Son("Jack","Programmer",18); console.log(father.getName());//Tom console.log(son.getName());//Jack//繼承父類(lèi)getName()方法 console.log(son.getAge());//18
多繼承(利用apply()方法實(shí)現(xiàn)多繼承)
function FatherA(name) { this.name = name ; this.getName = function () { return this.name; } } function FatherB(job) { this.job = job; this.getJob = function () { return this.job; } } function Son(name,job,age) { FatherA.apply(this,new Array(name)); FatherB.apply(this,new Array(job)); this.age = age; this.getAge = function () { return this.age; } } var fatherA = new FatherA("Tom"); var fatherB = new FatherB("Engineer"); var son = new Son("Jack","Programmer",18); console.log(fatherA.getName());//Tom console.log(fatherB.getJob());//Engineer console.log(son.getName());//Jack//繼承父類(lèi)FatherA的getName()方法 console.log(son.getJob());//Programmer//繼承父類(lèi)FatherB的getJob()方法 console.log(son.getAge());//18
原型鏈方法
function Father() { } Father.prototype.name = "Tom"; Father.prototype.getName = function () { return this.name; }; function Son() { } Son.prototype = new Father(); Son.prototype.age = 18; Son.prototype.getAge = function () { return this.age; }; var father = new Father(); var son = new Son(); console.log(father.getName());//Tom console.log(son.getName());//Tom//繼承父類(lèi)FatherA的getName()方法 console.log(son.getAge());//18
混合方式(call()+原型鏈)
function Father(name) { this.name = name; } Father.prototype.getName = function () { return this.name; }; function Son(name,age) { Father.call(this,name); this.age = age; } Son.prototype = new Father(); Son.prototype.getAge = function () { return this.age; }; var father = new Father("Tom"); var son = new Son("Jack",18); console.log(father.getName());//Tom console.log(son.getName());//Jack//繼承父類(lèi)Father的getName()方法 console.log(son.getAge());//18
多態(tài)機(jī)制實(shí)現(xiàn)
function Person(name) { this.name = name; if (typeof this.getName !== "function"){ Person.prototype.getName = function () { return this.name; } } if (typeof this.toEat !== "function"){ Person.prototype.toEat = function (animal) { console.log( this.getName() + "說(shuō)去吃飯:"); animal.eat(); } } } function Animal(name) { this.name = name; if (typeof this.getName !== "function"){ Animal.prototype.getName = function () { return this.name; } } } function Cat(name) { Animal.call(this,name); if (typeof this.eat !== "function"){ Cat.prototype.eat = function () { console.log(this.getName() + "吃魚(yú)"); } } } Cat.prototype = new Animal(); function Dog(name) { Animal.call(this,name); if (typeof this.eat !== "function"){ Dog.prototype.eat = function () { console.log(this.getName() + "啃骨頭"); } } } Dog.prototype = new Animal(); var person = new Person("Tom"); person.toEat(new Cat("cat"));//Tom說(shuō)去吃飯:cat吃魚(yú) person.toEat(new Dog("dog"));//Tom說(shuō)去吃飯:dog啃骨頭
以上這篇老生常談javascript的面向?qū)ο笏枷刖褪切【幏窒斫o大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
如何實(shí)現(xiàn)一個(gè)webpack模塊解析器
這篇文章主要介紹了如何實(shí)現(xiàn)一個(gè)webpack模塊解析器,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-10-10js屬性對(duì)象的hasOwnProperty方法的使用
這篇文章主要介紹了js屬性對(duì)象的hasOwnProperty方法的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02layui使用及簡(jiǎn)單的三級(jí)聯(lián)動(dòng)實(shí)現(xiàn)教程
這篇文章主要給大家介紹了關(guān)于layui使用及簡(jiǎn)單的三級(jí)聯(lián)動(dòng)的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12next.js?getServerSideProps源碼解析
這篇文章主要為大家介紹了next.js?getServerSideProps源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10javascript DOM 操作基礎(chǔ)知識(shí)小結(jié)
經(jīng)常用到j(luò)avascript對(duì)dom,喜歡這方便的朋友也很多,要想更好的對(duì)dom進(jìn)行操作,這些基礎(chǔ)一定要知道的。2010-04-04利用JavaScript實(shí)現(xiàn)一個(gè)日期范圍選擇器
日期范圍選擇器是一個(gè)常見(jiàn)的Web應(yīng)用功能,它允許用戶(hù)選擇一個(gè)日期范圍,本文我們將使用JavaScript來(lái)實(shí)現(xiàn)這個(gè)功能,感興趣的小伙伴可以了解下2024-01-01