国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

老生常談javascript的面向?qū)ο笏枷?/h1>
2019-11-19 15:43:11
字體:
供稿:網(wǎng)友

面向?qū)ο蟮娜蠡咎匦?/strong>

封裝(把相關(guān)的信息(無論數(shù)據(jù)或方法)存儲在對象中的能力)

繼承(由另一個(gè)類(或多個(gè)類)得來類的屬性和方法的能力)

多態(tài)(一個(gè)對象在不同情況下的多種形態(tài))

定義類或?qū)ο?/strong>

第一種:基于Object對象

var person = new Object();person.name = "Rose";person.age = 18;person.getName = function () { return this.name;};console.log(person.name);//Roseconsole.log(person.getName);//function () {return this.name;}console.log(person.getName());//Rose 

缺點(diǎn):不能創(chuàng)建多個(gè)對象。

第二種:基于字面量方式

var person = { name : "Rose", age : 18 , getName : function () {  return this.name; }};console.log(person.name);//Roseconsole.log(person.getName);//function () {return this.name;}console.log(person.getName());//Rose

優(yōu)點(diǎn):比較清楚的查找對象包含的屬性和方法;

缺點(diǎn):不能創(chuàng)建多個(gè)對象。

第三種:工廠模式

方式一:

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);//Roseconsole.log(person2.name);//Jackconsole.log(person1.getName === person2.getName);//false//重復(fù)生成函數(shù),為每個(gè)對象都創(chuàng)建獨(dú)立的函數(shù)版本 

優(yōu)點(diǎn):可以創(chuàng)建多個(gè)對象;

缺點(diǎn):重復(fù)生成函數(shù)getName(),為每個(gè)對象都創(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);//Roseconsole.log(person2.name);//Jackconsole.log(person1.getName === person2.getName);//true//共享同一個(gè)函數(shù)

優(yōu)點(diǎn):可以創(chuàng)建多個(gè)對象;

缺點(diǎn):從語義上講,函數(shù)getName()不太像是Person對象的方法,辨識度不高。

第四種:構(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);//Roseconsole.log(person2.name);//Jackconsole.log(person1.getName === person2.getName); //false//重復(fù)生成函數(shù),為每個(gè)對象都創(chuàng)建獨(dú)立的函數(shù)版本

優(yōu)點(diǎn):可以創(chuàng)建多個(gè)對象;

缺點(diǎn):重復(fù)生成函數(shù)getName(),為每個(gè)對象都創(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);//Roseconsole.log(person2.name);//Jackconsole.log(person1.getName === person2.getName); //true//共享同一個(gè)函數(shù) 

優(yōu)點(diǎn):可以創(chuàng)建多個(gè)對象;

缺點(diǎn):從語義上講,函數(shù)getName()不太像是Person對象的方法,辨識度不高。

第五種:原型方式

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);//Roseconsole.log(person2.name);//Rose//共享同一個(gè)屬性console.log(person1.getName === person2.getName);//true//共享同一個(gè)函數(shù)

缺點(diǎn):它省略了為構(gòu)造函數(shù)傳遞初始化參數(shù),這在一定程序帶來不便;另外,最主要是當(dāng)對象的屬性是引用類型時(shí),它的值是不變的,總是引用同一個(gè)外部對象,所有實(shí)例對該對象的操作都會(huì)影響其它實(shí)例:

function Person() {}Person.prototype.name = 'Rose';Person.prototype.age = 18;Person.prototype.lessons = ["語文","數(shù)學(xué)"];Person.prototype.getName = function () { return this.name;};var person1 = new Person();person1.lessons.push("英語");var person2 = new Person();console.log(person1.lessons);//["語文", "數(shù)學(xué)", "英語"]console.log(person2.lessons);//["語文", "數(shù)學(xué)", "英語"]//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);//Roseconsole.log(person2.name);//Jackconsole.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);//Roseconsole.log(person2.name);//Jackconsole.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);//Roseconsole.log(person2.name);//Jackconsole.log(person1.getName === person2.getName);//true//共享原型中定義的方法

對象屬性的擴(kuò)展及刪除

Javascript的對象可以使用 '.' 操作符動(dòng)態(tài)的擴(kuò)展其屬性,可以使用 'delete' 關(guān)鍵字或?qū)傩缘闹翟O(shè)置為 'undefined' 來刪除屬性。

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);//Engineerdelete person.job;//刪除屬性console.log(person.job);//undefined//刪除屬性后值為undefinedperson.age = undefined;//刪除屬性console.log(person.age);//undefined//刪除屬性后值為undefined

對象屬性類型

數(shù)據(jù)屬性

特性:

[configurable]:表示能否使用delete操作符刪除從而重新定義,或能否修改為訪問器屬性。默認(rèn)為true;

[enumberable]:表示是否可通過for-in循環(huán)返回屬性。默認(rèn)true;

[writable]:表示是否可修改屬性的值。默認(rèn)true;

[value]:包含該屬性的數(shù)據(jù)值。讀取/寫入都是該值。默認(rèn)為undefined;如上面實(shí)例對象person中定義了name屬性,其值為'My name',對該值的修改都反正在這個(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//重新賦值無效delete person.name;console.log(person.name);//Rose//刪除無效

注意:

一旦將configurable設(shè)置為false,則無法再使用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//重新賦值無效delete person.name;console.log(person.name);//Rose//刪除無效Object.defineProperty(person,"name",{configurable:true,writable:true});//Cannot redefine property: name

訪問器屬性

特性:

[configurable]:是否可通過delete操作符刪除重新定義屬性;

[numberable]:是否可通過for-in循環(huán)查找該屬性;

[get]:讀取屬性時(shí)調(diào)用,默認(rèn):undefined;

[set]:寫入屬性時(shí)調(diào)用,默認(rèn):undefined;

訪問器屬性不能直接定義,必須使用defineProperty()或defineProperties來定義:如下

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的讀取出來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}

對于數(shù)據(jù)屬性,可以取得:configurable,enumberable,writable和value;

對于訪問器屬性,可以取得:configurable,enumberable,get和set;

繼承機(jī)制實(shí)現(xiàn)

對象冒充

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());//Tomconsole.log(son.getName());//Jack//繼承父類getName()方法console.log(son.getAge());//18

多繼承(利用對象冒充可以實(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());//Tomconsole.log(fatherB.getJob());//Engineerconsole.log(son.getName());//Jack//繼承父類FatherA的getName()方法console.log(son.getJob());//Programmer//繼承父類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());//Tomconsole.log(son.getName());//Jack//繼承父類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());//Tomconsole.log(fatherB.getJob());//Engineerconsole.log(son.getName());//Jack//繼承父類FatherA的getName()方法console.log(son.getJob());//Programmer//繼承父類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());//Tomconsole.log(son.getName());//Jack//繼承父類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());//Tomconsole.log(fatherB.getJob());//Engineerconsole.log(son.getName());//Jack//繼承父類FatherA的getName()方法console.log(son.getJob());//Programmer//繼承父類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());//Tomconsole.log(son.getName());//Tom//繼承父類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());//Tomconsole.log(son.getName());//Jack//繼承父類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() + "說去吃飯:");   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() + "吃魚");  } }}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說去吃飯:cat吃魚person.toEat(new Dog("dog"));//Tom說去吃飯:dog啃骨頭

以上這篇老生常談javascript的面向?qū)ο笏枷刖褪切【幏窒斫o大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

主站蜘蛛池模板: 池州市| 新巴尔虎右旗| 高邑县| 米易县| 仪陇县| 麻城市| 会宁县| 泸定县| 城市| 连城县| 哈尔滨市| 莱州市| 镇江市| 峨山| 乌鲁木齐县| 广东省| 桦南县| 鲜城| 许昌县| 阆中市| 论坛| 桐庐县| 陕西省| 泸溪县| 晋江市| 陵川县| 平昌县| 元氏县| 鄂伦春自治旗| 阜平县| 陈巴尔虎旗| 丹寨县| 潞西市| 屏东县| 乌兰察布市| 乌审旗| 曲松县| 辽中县| 古丈县| 上虞市| 仁布县|