亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

在JavaScript中實現類的方式探討

2019-11-20 22:21:30
字體:
來源:轉載
供稿:網友
在 javascript 中有很多方式來創建對象,所以創建對象的方式使用起來非常靈活。那么,到底哪一種方式是最恰當的對象創建方式呢?構造模式,原型模式還是對象原意模式(Object literal)呢?

但這些模式具體是怎么回事呢?

在開始講解之前,讓我們先清楚地介紹一下關于 javascript 基本知識。

有沒有可能在 javascript 中實現面向對象編程的方式呢?

答案是可能的,javascript 是可以創建對象的!這種對象可以包含數據及能夠操作數據的方法,甚至可以包含其他對象。它沒有類但擁有構造函數;它沒有類繼承機制,但是可以通過原型(prototype)實現繼承。

現在看起來,我們已經了解了在 javascript 中創建對象及實現基于對象編程時所必須的組成部分。

我們都知道 javascript 擁有私有變量。一個通過“var”關鍵字定義的變量,只能在函數體中被訪問,而不能在函數外被訪問。那么,如果我們不通過使用“var”關鍵字來定義變量會怎樣呢?我們現在不對這個問題進行深入探討,可能是通過“this”進行訪問的,我會在另外的時間來詳細講述這個問題。

現在回到之前的問題。到底哪一種方式是最恰當的對象創建方式呢?
讓我們用已經知曉的知識,通過創建Person的對象是來試驗一下。
復制代碼 代碼如下:

var Person = {
firstName : 'John',
lastName : 'Cody',
fullName : '',
message : '',

createFullName : function () {
fullName = this.firstName + ' ' + this.lastName;
},

changeMessage : function (msg) {
this.message = msg;
},

getMessage : function () {
this.createFullName();
return this.message + ' ' + fullName;
}
}

Person.firstName = 'Eli';
Person.lastName = 'Flowers'
Person.changeMessage('welcome');
var message = Person.getMessage(); // welcome Eli Flowers
alert(message);

這是對象原意模式(literal pattern)。這非常接近我們常創建對象的方式。如果你不需要關心私有/包裝的成員,并且你知道不將創建這個對象的實例。那么,這種方式將會很適合你。公有的成員可以做所有私有成員的事情,不是嗎?但是,這不是一個類,而是一個對象而已,不能被創建實例并且不能被繼承。

讓我們嘗試下其他的方面:
復制代碼 代碼如下:

var Person = {
firstName : 'John',
lastName : 'Cody',
fullName : '',
message : '',

createFullName : function () {
fullName = this.firstName + ' ' + this.lastName;
},

changeMessage : function (msg) {
this.message = msg;
},

getMessage : function () {
this.createFullName();
return this.message + ' ' + fullName;
}
}

Person.firstName = 'Eli';
Person.lastName = 'Flowers'
Person.changeMessage('welcome');
var message = Person.getMessage(); // welcome Eli Flowers
alert(message);

這是一種構造模式的實例(Constructor Pattern)。那么,這是類還是對象呢?應該 兩種都算是吧。我們能夠在當請求時把它當做對象Person來使用。它畢竟也只是一個函數而已。然而,它可以通過使用“new”關鍵字來實現創建新的實例功能。

在使用這種方式時,我們需要時刻記住如下要點:

1. 無論什么時候這個函數被調用時,它擁有一個特別的變量叫做“this”并且可以在全局范圍內使用。全局范圍依賴于這個函數自身的作用范圍。

2. 無論什么時候通過“new”關鍵字創建這個函數的實例,“this”變量指向這個函數本身,并且這個“new”操作將會影響到函數體中的代碼被執行。這也正是構造模式。

3. 任何附加到“this”變量下的變量都會成為公有屬性并且任何通過“var”關鍵字定義的變量都將是屬于私有屬性。

4. 一個附加到“this”下的函數叫做特權函數,它可以訪問所有的私有變量以及被附加到“this”下的函數及變量。

5. 私有函數可以訪問到其他私有變量及私有函數。

6. 私有函數不能直接訪問被附加到“this”變量和函數。我們可以通過創建一個私有變量“_that”并且將它賦值為“this”的方式實現。

7. 任何私有變量及函數對于其他私有函數及其他被附加到“this”的函數是可用的。這完全是可能的再javascript的作用范圍下。

8. 一個變量:不是通過“var”關鍵字,也不是附加到“this”變量上以獲得全局作用范圍的。例如,對于一個自定義函數的作用范圍。需要再一次地了解作用域及集群的知識。

這已經實現了我們想要的大部分要求了,但是,有時候“this”和“that”這兩個入口變量很容易造成給人們帶來疑惑。尤其對于那些一直堅持要求純粹私有的人來說,更容易迷惑。

讓我們再稍微修改下試試吧。
復制代碼 代碼如下:

var Person = function () {

//private
var firstName = 'John';
var lastName = 'Cody';
var fullName = '';
var message = '';


var createFullName = function () {
fullName = firstName + ' ' + lastName;
}

//public setters
var setMessage = function (msg) {
message = msg;
}

var setFirstName = function (fName) {
firstName = fName;
}

var setLastName = function (lName) {
lastName = lName;
}

var getMessage = function () {
createFullName();
return message + ' ' + fullName;
}

//functions exposed public
return {
setFirstName: setFirstName,
setLastName: setLastName,
setMessage: setMessage,
getMessage: getMessage
};

};

var person1 = new Person();
person1.setFirstName('Eli');
person1.setLastName('Flowers');
person1.setMessage('welcome');
var message = person1.getMessage(); // welcome Eli Flowers
alert(message);

這是一個顯示模式(Revealing Pattern)。非常感謝 Christian Heilmann。使用這種模式的方式就是把請求的"getters" 和 "setters" 當作屬性使用。我們很多都是從傳統的Java編程中找到這樣的身影并且很明顯地知道實現它其實并不復雜。這同樣是一種類似于當類繼承自一個接口的情況。

這種模式大部分方面都實現得很好,僅僅只有一個很微小的問題。每一次當一個類的實例被創建時。這個新創建的對象獲得了一份變量和函數的拷貝?,F在,拷貝變量是沒有問題的,我們希望對于每一個對象的數據都是屬于對象自身的,那么,成員函數呢?他們僅僅是操作數據而已。那么,為什么需要拷貝他們呢?

這正是原型模式(Prototype)的優勢所在。在所有實例中,所有東西都是被創建成一個原型,并且能夠相互分享。我們僅僅需要做的就是依據原型創建共有函數。
復制代碼 代碼如下:

var Person = function () {

//private
var welcomeMessage = 'welcome';
var fullName = '';
var firstName = '';
var lastName = "";
var createFullName = function () {
Person.prototype.setFirstName('asdsad');
fullName = firstName + ' ' + lastName;
};

//constructor
var Person = function () { }; //will be created evrytime

//public
Person.prototype = {
getFullName: function () {
createFullName();
return welcomeMessage + ' ' + fullName;
},
setFirstName: function (fName) {
firstName = fName;
},
setLastName: function (lName) {
lastName = lName;
},
ChangeMessage: function (mesg) {
welcomeMessage = mesg;
}
}

return new Person(); // Person; //new Person();
};


var person1 = new Person();
person1.setFirstName ('Eli');
person1.setLastName('Flowers');
person1.ChangeMessage('welcome');
var message = person1.getFullName(); // welcome asdsad Flowers
alert(message);

原型模式存在的一個問題是它不能訪問私有變量及私有函數,正因為這個問題,我們才會介紹閉包以及始終組織好創建類中存在的代碼以使得它在全局范圍內不會變得很混亂。所有都是屬于 Person 類的作用范圍內。

另外一個問題是每一次實例被創建時,全部的代碼都被執行一遍,包括原型的綁定。對于我們中的一部分人來說,這僅僅只是一個效率問題。處理好這個問題的一種方式是僅僅在期望共有函數不可用的情況下綁定這個原型。

這樣將會使得綁定原型操作只會在第一個實例被創建時執行,并且在那之后所有其他的實例都將只會進行檢查操作。不幸的是,這樣還是不能解決我們在上面例子中提到的問題,因為我們只有重新再來一次創建的函數用于生成一個閉包來達到這個類的效果。這樣的話,至少我們減少了一部分內存的使用。

等等,還有另外一個問題是私有函數不能直接訪問原型函數。

為什么你們一定得需要私有函數和私有變量呢?我知道你一定是想實現類的封裝性,想確保類中的屬性或者內部的數據不會被突然地修改了或者被內部的其他程序所修改,或者任何其他的操作……

你應該記住你是不能將 javascript 代碼編譯成二進制的,對于這種情況,你在一定程度上很惱火吧,這樣代碼始終都是可用的。所以,如果任何人想攪亂代碼的話,不管你真正實現私有或者沒有實現私有,不管你將代碼給團隊中的其他成員或者賣出去,他們都可以攪亂代碼。實現私有化可能有那么一點點幫助吧。

另一個其他編程者使用的技術是使用約定命名,使用下劃線 “_”給所有你想設成私有任何的東西加上前綴以規定它成為私有。
復制代碼 代碼如下:

(function () {
var Person = function () {
this._fullName = '';
this.welcomeMessage = '';
this.firstName = '';
this.lastName = "";
_that = this;

this._createFullName = function () {
this.ChangeMessage('Namaste');
this._fullName = this.firstName + ' ' + this.lastName;
};
}

//Shared Functions for Code optimization
Person.prototype = {
constructor: Person,
getFullName: function () {
this._createFullName();
return this.welcomeMessage + ' ' + this._fullName;
},
ChangeMessage: function (mesg) {
this.welcomeMessage = mesg;
}
}

this.Person = Person;
})();

var person1 = new Person();
person1.firstName = 'Eli';
person1.lastName = 'Flowers';
person1.ChangeMessage('Welcome');
var message = person1.getFullName(); // Namaste Eli Flowers
alert(message);

我不是說你不應該考慮 “private” 或者類似的知識。你是代碼的設計者,所以你將知道怎么來管理并且知道怎么做才是最好的。根據你的需求,你可以使用任何一種設計模式或者多個設計模式組合一起使用。

無論你決定采用哪種設計模式,始終記住做盡量少的事情,不要在全局作用范圍內實現閉包,盡量減少內存泄露,以及優化代碼,并且組織好代碼。所以,盡量多了解些作用域,閉包以及 “this” 的表現行為。

最后,祝編程愉快!

譯后感

經常使用 javascript,對于它的印象一直都是直接拷貝過來就可以用的。最近使用 extjs,它的類框架非常好用。從這樣文章也明白在 javascript 中實現類的各種方式,以及在文章最后討論了類中私有成員的實現情況。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久五月情影视| 亚洲欧美在线x视频| 久久久久久久久久久成人| 欧美日韩国产综合视频在线观看中文| 久久伊人免费视频| 精品国产欧美一区二区三区成人| 97久久国产精品| 久久免费成人精品视频| 国产噜噜噜噜噜久久久久久久久| 亚洲美女精品久久| 欧美激情视频在线免费观看 欧美视频免费一| 精品视频一区在线视频| 日韩精品久久久久久福利| 国产欧美日韩中文字幕| 国产一区二区三区视频在线观看| 日韩在线欧美在线| 久久久久久久国产精品视频| 亚洲国内精品在线| 91欧美视频网站| 国产精品日韩欧美综合| 亚洲福利视频专区| 精品久久久一区二区| 欧美一区二区视频97| 日韩欧美有码在线| 91精品久久久久久久久中文字幕| 91影视免费在线观看| 国产精品视频免费观看www| 日本高清视频一区| 国产精品久久久久久av福利| 日韩中文字幕欧美| 色99之美女主播在线视频| 上原亚衣av一区二区三区| 九九热在线精品视频| 国产精品一区=区| 日韩av免费观影| 亚洲精品综合精品自拍| 国内精品模特av私拍在线观看| 91精品国产色综合| 日韩免费观看网站| 欧美成人精品在线播放| 成人av.网址在线网站| 国产成人91久久精品| 亚洲综合中文字幕在线| 91久久嫩草影院一区二区| 久久久亚洲国产天美传媒修理工| 亚洲第一精品夜夜躁人人爽| 国产欧美在线观看| 91产国在线观看动作片喷水| 国产精品久久久久免费a∨| 日韩欧美在线播放| 国产欧美日韩最新| 亚洲精品丝袜日韩| 日韩美女主播视频| 91探花福利精品国产自产在线| 91成人在线观看国产| 尤物yw午夜国产精品视频明星| 成人久久18免费网站图片| 成人黄色免费网站在线观看| 国产精品久久久久久久久免费看| 欧美激情2020午夜免费观看| 国产美女精品视频| 欧美制服第一页| 亚洲欧美国产高清va在线播| 国产精品久久久久久一区二区| 欧美日韩在线免费观看| 欧美国产日韩免费| 欧美韩国理论所午夜片917电影| 国产精品久久婷婷六月丁香| 97色在线视频| 国内精品久久影院| 97碰在线观看| 91久久久亚洲精品| 成人精品一区二区三区电影免费| 欧美精品久久久久久久| 亚洲美女激情视频| 最好看的2019的中文字幕视频| 久久精品99久久久久久久久| 亚洲小视频在线观看| 国产精品18久久久久久首页狼| 国模极品一区二区三区| 久久在线免费视频| 日韩欧美国产一区二区| 亚洲精品白浆高清久久久久久| 久久综合免费视频| 亚洲少妇中文在线| 欧美裸体视频网站| 日本精品一区二区三区在线播放视频| 亚洲精品美女在线观看播放| 亚洲国产精品久久久久秋霞蜜臀| 伊人久久男人天堂| 久久中国妇女中文字幕| 欧美性理论片在线观看片免费| 日本一本a高清免费不卡| 92看片淫黄大片看国产片| 国内免费精品永久在线视频| 日韩成人网免费视频| 欧美性xxxxx极品| 欧美高清videos高潮hd| 久久视频免费在线播放| 亚洲a成v人在线观看| 精品久久久久久久中文字幕| 成人欧美一区二区三区在线湿哒哒| 欧美在线视频a| 自拍偷拍亚洲精品| 欧洲日本亚洲国产区| 日韩有码在线电影| 色综合五月天导航| 日本精品免费一区二区三区| 最近免费中文字幕视频2019| 欧美高清视频在线| 久久久久久久久91| 国产午夜精品全部视频在线播放| 亚洲国产一区二区三区在线观看| 久久久视频免费观看| 国产精品稀缺呦系列在线| 久久久电影免费观看完整版| 欧美激情精品久久久久久免费印度| 国产精品日韩专区| 欧美国产日韩视频| 亚洲天堂成人在线视频| 97欧美精品一区二区三区| 色婷婷综合久久久久| 视频一区视频二区国产精品| 国产精品永久免费在线| 亚洲精品美女网站| 日本国产高清不卡| 欧美午夜精品久久久久久久| 成人h片在线播放免费网站| 亚洲激情在线观看视频免费| 久久91精品国产| 亚洲欧美中文日韩在线| 国产精品成人久久久久| 亚洲精品v欧美精品v日韩精品| 亚洲最大福利视频网| 欧美猛交免费看| 国产精品视频免费在线| 亚洲激情视频在线| 久久精品国产96久久久香蕉| 日韩在线欧美在线| 国产精品a久久久久久| 中文字幕不卡在线视频极品| 欧美黑人一区二区三区| www.久久久久久.com| 久久全球大尺度高清视频| 日韩综合视频在线观看| 日韩欧美亚洲综合| 欧美日韩亚洲精品一区二区三区| 国产精品va在线播放| 日韩美女主播视频| 亚洲最新中文字幕| 日韩中文字幕在线观看| 日韩视频免费看| 亚洲美女av网站| 欧洲亚洲免费视频| 亚州欧美日韩中文视频| 亚洲男人第一网站| 亚州精品天堂中文字幕| 久久精品夜夜夜夜夜久久| 一色桃子一区二区| 亚洲成人激情在线| 欧美高清视频一区二区| 91在线|亚洲| 成人免费在线网址| 亚洲黄色成人网|