[原]JavaScript必備知識系列-物件導向知識串結

來源:互聯網
上載者:User
摘要

最近在看JavaScript進階程式設計(第三版),物件導向一章20多頁,來來回回看了三五遍,每次看的收穫都不一樣。第一遍囫圇吞棗,不求甚解,感覺恍然大悟,結果晚上睡覺一想發現很多問題,什麼都不明白,再看第二遍,發現原來是這樣。過了幾天一用,發現手寫起來原來還是在憑記憶,於是下一遍,下一遍...

單憑記憶去弄清楚東西很不靠譜,時間一長腦袋空白。特別是技術上的很多思想和原理,只看不練,即便當時想得特別清楚,過久了也會忘。再者就是網上一些東西,只能說是提供了一種便捷的查看途徑,事後還是自己總結為好,畢竟大多都是個人總結,一些概念很難講的很清楚,而且兩個人談同一件事情,一般說的步驟和章節都是不同的,這樣很容易形成交叉記憶,越多交叉記憶越混亂。還是持懷疑的態度看東西好一點,動手試一下就知道到底是怎麼個樣子,知識串一下。高品質有保證的書或者官方的有些東西,是不錯的來源。

趁自己這會看得還算明白,腦袋還算清楚,記錄一下,做個備忘。概念性的東西是書上的,減少日後誤導。例子手寫加驗證,再畫個圖,以便以後一看就明白。

一、封裝

對象定義:ECMA-262把對象定義為:“無序屬性的集合,其中屬性可以包括基本值、對象或者函數”。

建立對象:每個對象都是基於一個參考型別建立的,這個參考型別可以是原生類型(Object, Array, Date, RegExp, Function, Boolean, Number, String),也可以是自訂類型。

1 、建構函式模式
function Person(name, age) {    this.name = name;    this.age = age;    this.sayName = function() {        alert(this.name);    }}通過以上建構函式使用new操作符可以建立對象執行個體。var zhangsan = new Person('zhangsan', 20);var lisi = new Person('lisi', 20);zhangsan.sayName();//zhangsanlisi.sayName();    //lisi

通過new建立對象經曆4個步驟

1、建立一個新對象;[var o = new Object();]

2、將建構函式的範圍賦給新對象(因此this指向了這個新對象);[Person.apply(o)]  [Person原來的this指向的是window]

3、執行建構函式中的代碼(為這個新對象添加屬性);

4、返回新對象。

通過代碼還原new的步驟:

function createPerson(P) {    var o = new Object();    var args = Array.prototype.slice.call(arguments, 1);    o.__proto__ = P.prototype;    P.prototype.constructor = P;    P.apply(o, args);    return o;}測試新的建立執行個體方法var wangwu = createPerson(Person, 'wangwu', 20);wangwu.sayName();//wangwu
2 、原型模式

原型對象概念:無論什麼時候,只要建立一個新函數,就會根據一組特定的規則為該函數建立一個prototype屬性,這個屬性指向函數的原型對象。在預設情況下,所有原型對象都會自動獲得一個constructor(建構函式)屬性,這個屬性包含一個指向 prototype 屬性所在函數的指標。而通過這個建構函式,可以繼續為原型對象添加其他屬性和方法。建立了自訂的建構函式後,其原型對象預設只會取得 constructor 屬性;至於其他方法,則都從 Object 繼承而來。當調用建構函式建立一個新執行個體後,該執行個體的內部將包含一個指標(內部屬性),指向建構函式的原型對象。ECMA-262第5版管這個指標叫 [[Prototype]] 。指令碼中沒有標準的方式訪問 [[Prototype]],但Firefox、Safari和Chrome在每個對象上都支援一個屬性__proto__;而在其他實現中,這個屬性對指令碼是完全不可見的。不過,要明確的真正重要的一點就是,這個串連存在於樣本和建構函式的原型對象之間,而不是存在於執行個體和建構函式之間。

這段話基本概述了建構函式、原型、樣本之間的關係,表示更清晰

function Person(name, age) {    this.name = name;    this.age = age;}Person.prototype.country = 'chinese';Person.prototype.sayCountry = function() {    alert(this.country);} var zhangsan = new Person('zhangsan', 20);var lisi = new Person('lisi', 20); zhangsan.sayCountry();    //chineselisi.sayCountry();        //chinese alert(zhangsan.sayCountry == lisi.sayCountry); //true

注意地方:建構函式的原型對象,主要用途是讓多個對象執行個體共用它所包含的屬性和方法。但這也是容易發生問題的地方,如果原型對象中包含參考型別,那麼應參考型別存的是指標,所以會造成值共用。如下:

Person.prototype.friends = ['wangwu']; //Person添加一個數群組類型zhangsan.friends.push('zhaoliu');  //張三修改會對李四造成影響alert(zhangsan.friends);  //wangwu,zhaoliualert(lisi.friends); //wangwu,zhaoliu李四也多了個 
3 、組合使用建構函式模式和原型模式

這種模式是使用最廣泛、認同度最高的一種建立自訂類型的方式。建構函式模式用於定義執行個體屬性,而原型模式用於定義方法和共用的屬性。這樣,每個執行個體都有自己的一份執行個體屬性的副本,同時有共用著對方法的引用,最大限度的節省了記憶體。

原型模式改造後的如下:

function Person(name, age) {    this.name = name;    this.age = age;    this.friends = ['wangwu'];} Person.prototype.country = 'chinese';Person.prototype.sayCountry = function() {    alert(this.country);} var zhangsan = new Person('zhangsan', 20);var lisi = new Person('lisi', 20); zhangsan.friends.push('zhaoliu');alert(zhangsan.friends); //wangwu,zhaoliualert(lisi.friends); //wangwu
二、繼承 繼承基本概念

ECMAScript主要依靠原型鏈來實現繼承(也可以通過拷貝屬性繼承)。

原型鏈基本思想是,利用原型讓一個參考型別繼承另外一個參考型別的屬性和方法。建構函式、原型、樣本的關係是:每個建構函式都有一個原型對象,原型對象都包含了一個指向建構函式的指標,而執行個體都包含了一個指向原型的內部指標。所以,通過過讓原型對象等於另外一個類型的執行個體,此時原型對象將包含一個指向另一個原型的指標,相應地,另一個原型中也包含這一個指向另一個建構函式的指標。假如另外一個原型又是另一個類型的執行個體,那麼上述關係依然成立,如此層層遞進,就構成了執行個體和原型的鏈條。這就是原型鏈的基本概念。

讀起來比較繞,不容易理解。直接通過執行個體說明驗證。

1 、原型鏈繼承
function Parent() {    this.pname = 'parent';}Parent.prototype.getParentName = function() {    return this.pname;} function Child() {    this.cname = 'child';}//子建構函式原型設定為父建構函式的執行個體,形成原型鏈,讓Child擁有getParentName方法 Child.prototype = new Parent(); Child.prototype.getChildName = function() {    return this.cname;} var c = new Child();alert(c.getParentName()); //parent

圖解:

原型鏈的問題,如果父類中包括了參考型別,通過Child.prototype = new Parent()會把父類中的參考型別帶到子類的原型中,而參考型別值的原型屬性會被所有執行個體共用。問題就回到了[一、2]節了。

2 、組合繼承 - 最常用繼承方

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.