1. 程式人生 > >Js中的物件、建構函式、原型、原型鏈及繼承

Js中的物件、建構函式、原型、原型鏈及繼承

1、物件

在傳統的面向過程的程式設計中,會造成函式或變數的冗餘。而JS中物件的目的是將所有的具有相同屬性或行為的程式碼整合到一起,形成一個集合,這樣就會方便我們管理,例如:

var person1={
    name:"tan",
    age:26,
    showMessage:function(){
        alert("name:"+this.name);
    }
};
person.showMessage();//輸出name:tan

以上的例子將name、age、showMessage放進person1這個物件中,方便了我們的管理同時也減少了我們的命名困難。

我們下面的講解會用到的基本知識點:

1)、記憶體會對每一個物件一個記憶體空間;

2)、函式也是一個物件。

每一個物件都會佔據一定的記憶體空間。

2、建構函式

以上可以看出物件的產生方便了我們的程式碼管理,但是又產生了一個問題,如果我又定義了一個物件person2,如下:

var person1={

   name:"song",

    age:16,

    showMessage:function(){

       alert("name:"+this.name);

    }

};

這樣就產生了程式碼的重複問題——person1與person2有同樣的屬性和行為,是不是能通過創造一個函式通過傳參來改變物件的屬性值,這樣就引出了建構函式的概念。

function Person(name,age)={

    this.name=name;

    this.age=age;

      this.showMessage=function(){

       alert("name:"+this.name);

    };

}

var person1=new Person(tan,26);

var person2=new Person(song,16);

這樣通過建構函式我們就不用反覆去重新定義屬性和行為,我們就創造了兩個物件person1和person2。person1和person2也叫作建構函式Person的兩個例項。

3、原型

看上去建構函式可以完美的解決我們的程式碼管理和重複性的問題。但是,正如在1中提到的函式也是一個物件,也會有一定的記憶體空間,屬性我們可以容忍每一個物件佔據一個空間,但方法也就是行為,他對每一個物件來說動作是一樣的,只是可能的引數不一樣。因此我們要想一個方法來解決記憶體空間被過多的佔用的問題。

擬解決方法1:函式的定義轉移到建構函式外,例如:

function Person(name,age)={

    this.name=name;

    this.age=age;

      this.showMessage=showMessage;

}

function showMessage(){

        alert("name:"+name);

}

這時建構函式中this.showMessage會指向showMessage這個全域性變數,先在建構函式的內部去找showMessage這個變數,然後去外部找(涉及到了作用域鏈的問題以後再說)。

這個解決方案看似很好,但一個物件若有多個方法時,程式碼的封裝性無法體現,而且全域性的函式只是為一個物件服務,則全域性性體現的不明顯。

擬解決方法2:原型

首先要知道,每一個函式在建立的時候都會預設的分配一個prototype屬性,建構函式也不例外。那麼 prototype屬性是什麼?

prototype是一個指標,它指向一個物件。指標就像是我想到存一本書在一間房子裡(這是一個行為),我要完成這個行為,我先要建房子然後把書放進房子裡,我下次要存一本新書,那麼我還要先建房子在放另一本書,是不是聽起來很麻煩,那麼更好的解決方法呢?整個行為房子是一個確定的動作,不需要每次都重建,我建一次把房子的地址記下來,以後我每一次有放書這個動作時只需要通過地址找到對應的房子就行了。如上面的例子showMessage就是建房子的動作,name是書,protoype屬性是地址。建構函式就是每放一本書就要建一個房子,而原型就是通過地址去尋找房子。

//建房子

function Person(){

}

//房子裡有什麼並確定了指標的指向

Person.prototype={

        name:"tan",

        age:"22",

        showMessage:function(){

               alert("name:"+this.name);

        }

};

var person1 = new Person();

person1這樣就有了指標,就能訪問指標指向的記憶體空間。
我想你們應該有以下的疑問:

1)物件person1是否可以有自己的屬性?

可以有,而且對於person1和原型Person中都有的屬性,先考慮的是person1中的屬性。

2)是否能通過person1改變原型屬性值:

對不起,不可以,例項person1只是獲取了一個指向原型的指標,他並沒有改變原型的權利。但有一點要特別注意,對於包含引用型別的屬性——列如陣列。有一些操作是允許通過地址去訪問記憶體的,列如push,這些操作就有可能改變原型屬性,這個改變會造成災難性的後果,因為所有引用這個原型的物件都會隨之改變。
4、組合使用建構函式和原型來創造物件(自定義型別,也叫引用型別)

這是常用的自定義型別的建立方式,建構函式用來定義例項屬性,而原型用於定義方法和共享屬性。因此,每一個例項都會有自己的一份例項屬性的副本,但同時又共享著對方法的引用,最大限度的節約了記憶體。例如:

function Person(name,age){

        this.name=name;

        this.age=age;

}

//房子裡有什麼並確定了指標的指向

Person.prototype={

        construction:Person,

        showMessage:function(){

               alert("name:"+this.name);

        }

};

var person1 = newPerson("tan",22);

prototype中的預設的construction屬性,讓原型指向建構函式,預設是Person。

5、原型鏈與繼承

我們以上說的都是同類型下的物件,person1和person2都是Person的例項。假如我有Person和Man兩個引用型別,Person中的屬性和方法是有Man需要的,我想偷懶直接從

Person中所有的屬性和方法拿過來,這就是繼承。那麼我作為一個繼承的引用型別我能獲得誰的屬性和方法,那麼在這個問題上就會有原型鏈的概念。當物件嘗試獲某個屬性時,該物件沒有,會嘗試從原型物件中去找,原型物件沒有,在從原型物件的原型去找,最後到達Object.prototype。

 例如:

function Person(name,age){
this.pname=name;
this.page=age; 
}
Person.prototype={
showPMessage:function(){
alert("name:"+this.pname);
}
};
function Man(name,age){
        this.mname=name;
this.mage=age; 
}

//這一句話表示原型的指標指向了Person
Man.prototype = new Person("tan",22,"man");

//給原型新增方法一定要放在替換原型的語句之後
Man.prototype.test="wosi";
Man.prototype.showMMessage=function(){
alert("name:"+this.mname);
};

var song=new Man("song",1);
song.showMMessage();//顯示song

song.showPMessage();//顯示tan

相關推薦

Js物件建構函式原型原型繼承

1、物件 在傳統的面向過程的程式設計中,會造成函式或變數的冗餘。而JS中物件的目的是將所有的具有相同屬性或行為的程式碼整合到一起,形成一個集合,這樣就會方便我們管理,例如: var person1={     name:"tan",     age:26,     sho

通過物件建構函式深入理解js原型

說一些題外話 在最近的實習工作中因大量涉及到原生js的編寫,因此在工作之餘重新拿起紅寶書閱讀,每重新看一遍都受益匪淺,最近又讀到了js中難點原型、原型鏈,這裡僅是本人對js原型的理解和觀點,若有槽點錯誤之處,希望不吝賜教。 接下來我們就直奔主題 怎樣建立物件?

JS面向物件基礎講解(工廠模式建構函式模式原型模式混合模式動態原型模式)

什麼是面向物件?面向物件是一種思想!(廢話)。   面向物件可以把程式中的關鍵模組都視為物件,而模組擁有屬性及方法。這樣我們如果把一些屬性及方法封裝起來,日後使用將非常方便,也可以避免繁瑣重複的工作。接下來將為大家講解在JS中面向物件的實現。    工廠模式   工廠模式是軟體工程領

《隨筆一》——C#的“靜態建構函式物件初始化語句”

  靜態建構函式 ● 我們在使用類中的靜態成員時,先要初始化這些成員。 在宣告靜態成員時、可以同時提供一個初始值。 但有時候我們需要執行更復雜的初始化操作, 這應該怎麼辦呢? ● 我們可以把建構函式宣告成static的, 一般來說, 靜態的建構函式初始化類的靜態欄位

javascript物件函式建構函式原型作用域閉包this概論

1、物件 一切引用型別都是物件,函式function其實也是物件。物件多用字面量表示法建立。所有物件都是鍵值對的集合,這個值當然也可以是物件/函式,可以有很多層級,這個跟json有點像,在現代化js裡,json和js物件可以無縫轉換。 2、函式 函式是一種特殊的物件,函式名只是函式的

深入理解JavaScript函式建構函式物件prototype(原型物件)的關係。

學了這麼久前端,一直搞不明白函式與物件之間的關係,實在慚愧,是時候總結一下了。。以下是學習時的記錄,若有錯誤之處,請指出。。 首先我們要知道js中的資料型別有以下幾種: Number   Boolean   undefined     Object &

例項物件建構函式原型之間的關係

首先轉載一張圖(轉自:https://www.cnblogs.com/lml-lml/p/6880757.html):例項物件擁有__proto__和constructor屬性,前者指向建構函式的原型,後者指向建構函式;建構函式與普通函式不一樣,多擁有一個prototype屬

javascript原型物件建構函式和例項物件

大家都知道,javascript中其實並沒有類的概念。但是,用建構函式跟原型物件卻可以模擬類的實現。在這裡,就先很不嚴謹的使用類這個詞,以方便說明。 下面整理了一些關於javascript的建構函式、原型物件以及例項物件的筆記,有錯誤的地方,望指正。 先用一張圖簡單的概括下

this指標在普通函式物件方法定時器建構函式事件函式call()apply()的執行

前導: this是JavaScript中的一個關鍵字,在不同的場景中,this指向的物件也不同。在其他面嚮物件語言中(如C#),this就是指向當前物件。而在JavaScript 中this是在程式碼執行時繫結的,相對而言this指向比較混亂。在程式碼執行時th

Java子類與父類靜態程式碼塊非靜態程式碼塊建構函式的執行順序一覽表

子類Child繼承父類Parent Child child=new Child(); 執行順序如下: ①父類靜態程式碼塊>>②子類靜態程式碼塊>>③父類非靜態程式碼塊>>④父類建構函式>>⑤子類非靜態程式碼塊>>⑥子類

js物件轉化成字串數字或布林值的轉化規則

js中物件可以轉化成 字串、數字、布林值 一、物件轉化成字串: 規則: 1、如果物件有toString方法,則呼叫該方法,並返回相應的結果;(程式碼通常會執行到這,因為在所有物件中都有toString方法) 2、如果物件有valueOf方法,則呼叫該方法,並返回相應的結果; 3、否則丟擲異常。 通常,所有物件

談談JavaScript的原型原型建構函式prototype__proto__和constructor

  原型、原型鏈、建構函式是JavaScript比較難的知識點,但是它們又功能強大,是我們進行元件開發、模組開發必須掌握的技能,翻閱網上相關的博文,個人覺得這幾篇博文不錯,可以一讀:   1)湯姆大叔:強大的原型和原型鏈   2)深入理解JavaScript系列(10):JavaScript

工廠模式建構函式模式與原型模式

工廠模式 用函式來封裝以特定介面建立物件的細節 function createPerson(name,age,job){ var o=new Object(); o.name=name; o.age=age; o.job=job;

面向物件思想:類和物件封裝建構函式

面向物件的特點: 面向物件是一種更符合我們思考習慣的思想,它可以將複雜的事件簡單化,並將我們從執行者變成指揮者。 面向過程-強調步驟 面向過程-強調物件,這裡的物件就是洗衣機。 面向物件的語

Java第十五天學習筆記~常用物件API(Spring類特點建構函式常用方法)

常用物件API-----Spring類 一、特點 字串是一個特殊的物件 字串物件一旦被初始化就不會被改變 package day15; public class StringDemo { public static void main(String[] args)

理解JS原型物件建構函式物件之間的關係

第一次看原型的時候感覺沒咋看懂,這周又重新把原型物件,建構函式,物件看了一遍,理解頗多。在理解這三者及這三者的關係之前必須先熟悉的掌握一些前提知識,不然容易混淆。 前提補充: 物件(鍵值對的集合)的動態特性: 物件創建出來為物件新增新的屬性和方法/訪問物件的方法和屬性:

js物件陣列的深拷貝

通常我們對陣列、物件、物件陣列進行簡單賦值運算只是建立了一份原內容的引用,指向的仍然是同一塊記憶體區域,修改時會對應修改原內容,而有時候我們並不需要這種模式,這就需要對內容進行深拷貝。 一、陣列的深拷貝 方法1:遍歷複製 var arr = ["a", "b"], arrCopy = [

Java類的靜態屬性靜態程式碼塊塊非靜態屬性非靜態程式碼塊塊建構函式在初始化時的執行順序

序言   前幾天在複習J2SE的時候,看到了這個Java類在new的過程中,靜態域、靜態塊、非靜態域、非靜態塊、建構函式的執行順序問題。就想著自己總結寫一下,便於以後查閱總結:    以下是我整理好的結果;在java類new一個物件的過程中,它們的執行順序如下:     (當

類和物件(欄位=變數方法=函式方法過載靜態成員屬性建構函式)

一、類 類包括:欄位(用來儲存資料)、屬性(用來保護欄位,屬性的本質是兩個函式get和set)、建構函式(用來初始化物件,給物件的每一個屬性賦值)、函式(描述物件的行為)、索引器(以索引的方式去訪問物件)。 一個類都可以包含兩種成員:欄位(Field)與方法(Method)

java靜態塊類的屬性變數ClassA classA = new ClassA(); 建構函式的執行順序

1.先看如下程式,判斷執行的 結果:package com.dbzhang.demo; /** * 驗證類在被初始化的時候的執行順序 * 靜態程式碼塊:static{...} * 類的屬性變數:ClassA classA = new ClassA(); * 構造方法: