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

首頁 > 編程 > JavaScript > 正文

JavaScript編程中實現對象封裝特性的實例講解

2019-11-20 09:36:27
字體:
來源:轉載
供稿:網友

1.prototype對象
1.1構造函數的缺點
JavaScript通過構造函數生成新對象,因此構造函數可以視為對象的模板。實例對象的屬性和方法,可以定義在構造函數內部。

function Cat (name, color) { this.name = name; this.color = color;}var cat1 = new Cat('大毛', '白色');cat1.name // '大毛'cat1.color // '白色'

上面代碼的Cat函數是一個構造函數,函數內部定義了name屬性和color屬性,所有實例對象都會生成這兩個屬性。但是,這樣做是對系統資源的浪費,因為同一個構造函數的對象實例之間,無法共享屬性。

function Cat(name, color) { this.name = name; this.color = color; this.meow = function () { console.log('mew, mew, mew...'); };}var cat1 = new Cat('大毛', '白色');var cat2 = new Cat('二毛', '黑色');cat1.meow === cat2.meow// false

上面代碼中,cat1和cat2是同一個構造函數的實例。但是,它們的meow方法是不一樣的,就是說每新建一個實例,就會新建一個meow方法。這既沒有必要,又浪費系統資源,因為所有meow方法都是同樣的行為,完全應該共享。

1.2 prototype屬性的作用
在JavaScript語言中,每一個對象都有一個對應的原型對象,被稱為prototype對象。定義在原型對象上的所有屬性和方法,都能被派生對象繼承。這就是JavaScript繼承機制的基本設計。

除了這種方法,JavaScript還提供了另一種定義實例對象的方法。我們知道,構造函數是一個函數,同時也是一個對象,也有自己的屬性和方法,其中有一個prototype屬性指向另一個對象,一般稱為prototype對象。該對象非常特別,只要定義在它上面的屬性和方法,能被所有實例對象共享。也就是說,構造函數生成實例對象時,自動為實例對象分配了一個prototype屬性。

function Animal (name) { this.name = name;}Animal.prototype.color = "white";var cat1 = new Animal('大毛');var cat2 = new Animal('二毛');cat1.color // 'white'cat2.color // 'white'

上面代碼對構造函數Animal的prototype對象,添加了一個color屬性。結果,實例對象cat1和cat2都帶有該屬性。

更特別的是,只要修改prototype對象,變動就立刻會體現在實例對象。

Animal.prototype.color = "yellow";cat1.color // 'yellow'cat2.color // 'yellow'

上面代碼將prototype對象的color屬性的值改為yellow,兩個實例對象的color屬性的值立刻就跟著變了。這是因為實例對象其實沒有color屬性,都是讀取prototype對象的color屬性。也就是說,當實例對象本身沒有某個屬性或方法的時候,它會到構造函數的prototype對象去尋找該屬性或方法。這就是prototype對象的特殊之處。

如果實例對象自身就有某個屬性或方法,它就不會再去prototype對象尋找這個屬性或方法。

cat1.color = 'black';cat2.color // 'yellow'Animal.prototype.color // "yellow";

上面代碼將實例對象cat1的color屬性改為black,就使得它不用再去prototype對象讀取color屬性,后者的值依然為yellow。

總而言之,prototype對象的作用,就是定義所有實例對象共享的屬性和方法,所以它也被稱為實例對象的原型,而實例對象可以視作從prototype對象衍生出來的。

Animal.prototype.walk = function () { console.log(this.name + ' is walking.');};

上面代碼在Animal.protype對象上面定義了一個walk方法,這個方法將可以在所有Animal實例對象上面調用。

1.3原型鏈
由于JavaScript的所有對象都有構造函數,而所有構造函數都有prototype屬性(其實是所有函數都有prototype屬性),所以所有對象都有自己的prototype原型對象。

因此,一個對象的屬性和方法,有可能是定義它自身上面,也有可能定義在它的原型對象上面(就像上面代碼中的walk方法)。由于原型本身也是對象,又有自己的原型,所以形成了一條原型鏈(prototype chain)。比如,a對象是b對象的原型,b對象是c對象的原型,以此類推。因為追根溯源,最源頭的對象都是從Object構造函數生成(使用new Object()命令),所以如果一層層地上溯,所有對象的原型最終都可以上溯到Object.prototype。那么,Object.prototype有沒有原型呢?回答可以是有,也可以是沒有,因為Object.prototype的原型是沒有任何屬性和方法的null。

Object.getPrototypeOf(Object.prototype)// null

上面代碼表示Object.prototype對象的原型是null,由于null沒有任何屬性,所以原型鏈到此為止。

“原型鏈”的作用在于,當讀取對象的某個屬性時,JavaScript引擎先尋找對象本身的屬性,如果找不到,就到它的原型去找,如果還是找不到,就到原型的原型去找。以此類推,如果直到最頂層的Object.prototype還是找不到,則返回undefined。

舉例來說,如果讓某個函數的prototype屬性指向一個數組,就意味著該函數可以用作數組的構造函數,因為它生成的實例對象都可以通過prototype屬性調用數組方法。

function MyArray (){}MyArray.prototype = new Array();MyArray.prototype.constructor = MyArray;var mine = new MyArray();mine.push(1, 2, 3);mine.length // 3mine instanceof Array // true

上面代碼的mine是MyArray的實例對象,由于MyArray的prototype屬性指向一個數組,使得mine可以調用數組方法(這些方法其實定義在數組的prototype對象上面)。至于最后那行instanceof表達式,我們知道instanceof運算符用來比較一個對象是否為某個構造函數的實例,最后一行表示mine為Array的實例。

mine instanceof Array// 等同于(Array === MyArray.prototype.constructor) ||(Array === Array.prototype.constructor) ||(Array === Object.prototype.constructor )

上面代碼說明了instanceof運算符的實質,它依次與實例對象的所有原型對象的constructor屬性(關于該屬性的介紹,請看下一節)進行比較,只要有一個符合就返回true,否則返回false。

1.4 constructor屬性
prototype對象有一個constructor屬性,默認指向prototype對象所在的構造函數。

function P() {}P.prototype.constructor === P// true

由于constructor屬性定義在prototype對象上面,意味著可以被所有實例對象繼承。

function P() {}var p = new P();p.constructor// function P() {}p.constructor === P.prototype.constructor// truep.hasOwnProperty('constructor')// false

上面代碼表示p是構造函數P的實例對象,但是p自身沒有contructor屬性,該屬性其實是讀取原型鏈上面的P.prototype.constructor屬性。

constructor屬性的作用是分辨prototype對象到底定義在哪個構造函數上面。

function F(){};var f = new F();f.constructor === F // truef.constructor === RegExp // false

上面代碼表示,使用constructor屬性,確定變量f的構造函數是F,而不是RegExp。

2.Object.getPrototypeOf方法
Object.getPrototypeOf方法返回一個對象的原型。

// 空對象的原型是Object.prototypeObject.getPrototypeOf({}) === Object.prototype// true// 函數的原型是Function.prototypefunction f() {}Object.getPrototypeOf(f) === Function.prototype// true// 假定F為構造函數,f為F的實例對象// 那么,f的原型是F.prototypevar f = new F();Object.getPrototypeOf(f) === F.prototype// true

3.Object.create方法
Object.create方法用于生成新的對象,可以替代new命令。它接受一個對象作為參數,返回一個新對象,后者完全繼承前者的屬性,即前者成為后者的原型。

var o1 = { p: 1 };var o2 = Object.create(o1);o2.p // 1

上面代碼中,Object.create方法在o1的基礎上生成了o2。此時,o1成了o2的原型,也就是說,o2繼承了o1所有的屬性的方法。

Object.create方法基本等同于下面的代碼,如果老式瀏覽器不支持Object.create方法,可以用下面代碼自己部署。

if (typeof Object.create !== "function") { Object.create = function (o) { function F() {} F.prototype = o; return new F(); };}

上面代碼表示,Object.create方法實質是新建一個構造函數F,然后讓F的prototype屬性指向作為原型的對象o,最后返回一個F的實例,從而實現讓實例繼承o的屬性。

下面三種方式生成的新對象是等價的。

var o1 = Object.create({});var o2 = Object.create(Object.prototype);var o3 = new Object();

如果想要生成一個不繼承任何屬性(比如toString和valueOf方法)的對象,可以將Object.create的參數設為null。

var o = Object.create(null);o.valueOf()// TypeError: Object [object Object] has no method 'valueOf'

上面代碼表示,如果對象o的原型是null,它就不具備一些定義在Object.prototype對象上面的屬性,比如valueOf方法。

使用Object.create方法的時候,必須提供對象原型,否則會報錯。

Object.create()// TypeError: Object prototype may only be an Object or null

Object.create方法生成的新對象,動態繼承了原型。在原型上添加或修改任何方法,會立刻反映在新對象之上。

var o1 = { p: 1 };var o2 = Object.create(o1);o1.p = 2;o2.p// 2

上面代碼表示,修改對象原型會影響到新生成的對象。

除了對象的原型,Object.create方法還可以接受第二個參數,表示描述屬性的attributes對象,跟用在Object.defineProperties方法的格式是一樣的。它所描述的對象屬性,會添加到新對象。

var o = Object.create(Object.prototype, { p1: { value: 123, enumerable: true }, p2: { value: "abc", enumerable: true }});o.p1 // 123o.p2 // "abc"

由于Object.create方法不使用構造函數,所以不能用instanceof運算符判斷,對象是哪一個構造函數的實例。這時,可以使用下面的isPrototypeOf方法,判讀原型是哪一個對象。

4.isPrototypeOf方法
isPrototypeOf方法用來判斷一個對象是否是另一個對象的原型。

var o1 = {};var o2 = Object.create(o1);var o3 = Object.create(o2);o2.isPrototypeOf(o3) // trueo1.isPrototypeOf(o3) // true

上面代碼表明,只要某個對象處在原型鏈上,isProtypeOf都返回true。

5.一個簡單示例

var ClassDemo = function () { //靜態private變量 var private_static_var = 'aaaa'; //靜態private方法 var private_static_func = function (key) {   return key + private_static_var; } //private方法,關鍵就是第一參數self要傳入this var private_func = function (self, key) {   return private_static_func(key + self.id); } var _class = function (id) { //構造函數  this.id = id; //public變量 } //public方法 _class.prototype.public_func = function (key) {   return private_func(this, key); } return _class;}();var a = new ClassDemo('hello world');alert(a.public_func('world hello'));

沒有簡單的辦法實現private變量和public靜態變量/方法,不過封裝到這個程度夠用了

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人激情视频在线观看| 亚洲人精选亚洲人成在线| 久久国产精品视频| 狠狠躁夜夜躁人人爽天天天天97| 久久久国产视频| 欧美最猛黑人xxxx黑人猛叫黄| 中文字幕久久久| 免费91麻豆精品国产自产在线观看| 亚洲人成电影网| 九色精品免费永久在线| 欧美成人三级视频网站| 亚洲男人天堂久| 成人免费视频网| 在线电影欧美日韩一区二区私密| 蜜臀久久99精品久久久无需会员| 精品日本高清在线播放| 日韩成人在线电影网| 国产高清在线不卡| 欧美人与性动交| 久热精品视频在线| 日韩中文字幕免费| 欧美激情视频一区二区三区不卡| 精品女厕一区二区三区| 精品中文字幕乱| 亚洲成人精品在线| 欧美在线观看一区二区三区| 中文字幕九色91在线| 日韩在线观看高清| 国产精品久久一| 日韩激情在线视频| 亚洲乱亚洲乱妇无码| 国产精品美乳在线观看| 国产成人激情小视频| 亚洲人成在线免费观看| 国产精品成人在线| 久久久久北条麻妃免费看| 久久99青青精品免费观看| 亚洲激情视频网| 日韩欧美a级成人黄色| 国产精品久久9| 91av视频在线| 亚洲图片欧美日产| 亚洲成人动漫在线播放| 久久久在线免费观看| 亚洲国产精彩中文乱码av在线播放| 最近2019年好看中文字幕视频| 97视频网站入口| 91沈先生在线观看| 国产精品亚洲一区二区三区| 亚洲精品久久久久久久久久久久| 日韩精品在线第一页| 欧美日韩性视频| 亚洲精品成人免费| 精品中文视频在线| 欧美一级bbbbb性bbbb喷潮片| 97国产真实伦对白精彩视频8| 海角国产乱辈乱精品视频| 日本中文字幕不卡免费| 国产精品亚洲美女av网站| 久久国产精品久久久久久久久久| 亚洲人免费视频| 国产亚洲精品成人av久久ww| 久久久伊人欧美| 成人午夜一级二级三级| 国产欧美日韩亚洲精品| 国产精品高潮呻吟久久av野狼| 欧美成人h版在线观看| 91国产视频在线| 国产精品久久久久久久久免费| 亚洲色图综合久久| 免费不卡在线观看av| 亚洲 日韩 国产第一| 日韩在线视频二区| 欧美日韩在线视频一区| 91亚洲精品在线| 久久久久中文字幕| 欧美理论电影在线播放| 欧美中文在线免费| 精品久久久久久久久中文字幕| 国产午夜精品美女视频明星a级| 精品久久久久久久久久久久| 日韩av在线直播| 91精品国产91久久久久久吃药| 欧美自拍视频在线| 中文字幕日韩av| 亚洲福利视频二区| 欧美激情亚洲另类| 日韩中文字幕在线免费观看| 午夜免费日韩视频| 欧美激情高清视频| 国产精品av网站| 国产精品露脸av在线| 日韩在线观看精品| 久久久久久久久国产精品| 精品久久久久久久久久久久久| 日韩麻豆第一页| 国产精品久久久久久久久| 国产精品国产自产拍高清av水多| 欧洲精品毛片网站| 亚洲国产精品中文| 久久视频在线直播| 欧美又大粗又爽又黄大片视频| 国产精品免费小视频| 美女撒尿一区二区三区| 欧美一级淫片videoshd| 国产suv精品一区二区| 国产精品久久久一区| 欧美乱大交xxxxx另类电影| 欧美高清一级大片| 国产亚洲精品美女久久久| 国产亚洲欧美日韩精品| 国产欧美一区二区三区在线| 久久久久久久久91| 上原亚衣av一区二区三区| 亚洲欧美一区二区三区情侣bbw| 欧美性在线视频| 国产主播在线一区| 国产精品永久免费观看| 色噜噜久久综合伊人一本| 亚洲精品国产综合久久| 久久久久久久久久久国产| 久青草国产97香蕉在线视频| 美日韩精品免费观看视频| 日韩一区在线视频| 成人97在线观看视频| 久久久综合免费视频| 亚洲高清在线观看| 最近中文字幕mv在线一区二区三区四区| 成人午夜小视频| 国产97在线亚洲| 欧美性猛交99久久久久99按摩| 中文字幕久久精品| 日韩中文字幕亚洲| 午夜精品国产精品大乳美女| 亚洲成人激情视频| 国产亚洲人成网站在线观看| 成人网中文字幕| 国产精品高精视频免费| 久久精品国产亚洲| 日韩福利伦理影院免费| 久久久久久国产免费| 国产丝袜一区视频在线观看| 久久精品国产久精国产一老狼| 亚洲国产精品中文| 国产色婷婷国产综合在线理论片a| 亚洲乱码av中文一区二区| 成人免费在线视频网址| 国产精品爽黄69天堂a| 国色天香2019中文字幕在线观看| 日韩资源在线观看| 最近2019中文字幕在线高清| 日韩欧美一区视频| 国产精品久久久久久久久久久不卡| 久久91亚洲精品中文字幕| 欧美日韩第一页| 成人激情视频在线观看| 国产在线不卡精品| 欧美理论电影在线观看| 91精品国产九九九久久久亚洲| 国产精品一香蕉国产线看观看| 欧美成年人视频网站欧美| 最近2019中文字幕在线高清| 久久久久中文字幕| 亚洲欧美激情一区|