国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript的prototype的理解

icattlecoder / 1690人閱讀

摘要:另外,首字母大寫是我們用以區分構造函數和普通函數的語法習慣,沒有強制規定一定要大寫。這個對象和構造函數的指向的是同一個對象。

prototype是JavaScript比較難理解的一部分,繞來繞去的。不理出頭緒來,理解原型的概念是件頭疼的事情。
為了方便后面的說明,先從對象說起。

對象 廣義對象

JavaScript里任何事物都是對象,不管什么,都是從Objec衍生出來的。function,array,string,{},都是對象。只是大家的功能各有不同。Object就像女媧,JavaScript世界的任何事物,都是它“創造”的。這里的對象是廣義的泛指的對象,是一切事物的統稱。

狹義對象

狹義對象是指一般的對象類型,通過var p = new Object()或者通過var p = {}的方式創建出來的東西。用來表示某一種事物,包含事物的屬性和方法。后面我們說的對象就是狹義對象,專門指JavaScript里產生出來的實例對象。其他的函數、數組等我們只從它本身的功能角度來看待,不當作對象,看成是執行功能、儲存數據的一種工具。

對象的產生 對象的創建

我們創建一個對象最常用的方法時var p = {},這只是JavaScript創建對象的快捷方式,其根本是通過var p = new Object()的方式產生。這種方式是通過構造函數來創建對象的。

構造函數 構造函數創建對象

如何通過構造函數來創建對象呢?網上有很多資料,這里簡單敘述一下。有如下構造函數:

function Person(name) {
    this.name = name; // 屬性
    this.run = function() { // 方法
        console.log("I"m running");
    }
}

上面是一個簡單的構造函數。構造函數它首先是一個函數,跟我們平常寫的函數是同一類。不同的是它里面有一個this指針,指向通過它產生的實例對象。另外,首字母大寫是我們用以區分構造函數和普通函數的語法習慣,沒有強制規定一定要大寫。但為了方便理解最好用首字母大寫的命名習慣來命名。

var p = new Person();

通過new的方式創建實例。上面變量p就是一個實例對象,它包含了一個name屬性和一個run方法。用new 構造函數創建對象的過程有兩步:

在內存中開辟一塊內存地址,用以存放新的實例對象

實例對象調用構造函數,那么里面的this指針指向這個實例,從而為對象設置了name屬性和run方法。

name屬性和run方法將是實例對象自身的東西,屬于對象自有。相當于你看到的結果是這樣一個對象:

p = {
    name: "Pelemy",
    run: functioin() {
        cosole.log("I"m running");
    }
}
實例對象重復創建的問題

按照上面的步驟創建對象,每執行一次 new Person() 就會有一個新的對象產生。

var p1 = new Person(); // 新對象,新的內存空間
var p2 = new Person(); // 新對象,新的內存空間
console.log(p1 === p2); // false
console.log(p1.run === p2.run) // false

每個對象都有自己name屬性和run方法。這里有個問題,每個實例對象run方法的實現都是一樣的,這是一個雷同的方法。雷同的方法每個人都有一個,這很浪費資源。如果有一個地方共享,同一種類的對象都去共享的地方取就好了,不需要每個都留一個備份在自己身上。為了處理這種情況,prototype產生了。

構造函數的prototype屬性

構造函數中this指針設置的屬性和方法將是新實例對象自身擁有的屬性和方法,我們叫本地屬性和方法。為了使各個產生的實例對象不重復設置相同的屬性或方法,JavaScript把這部分放到了構造函數的一個地方,這個地方就是構造函數的prototype屬性指向的對象(注意這里的對象也是前面說的狹義對象)。prototype本意是原型、藍圖,在這里我認為把它叫做“引用屬性”來理解更貼切。還是以前面的例子。

function Person(name) {
    this.name = name; // 定義本地屬性
}
Person.prototype.run = function() { // 定義引用方法
    console.log("I"m running");
}

這里可能會突然讓人頭疼。Person.prototype.run突然多了這么長一串,連續三個點。我們一個個看。首先把prototype當作一個屬性,就像我們常寫一個對象的屬性那樣,比如 car.color, car.speed。這里也一樣,prototype是構造函數的一個屬性,它的值是一個對象

Person.prototype = {
 // properties and methods
}

這個對象就是將來我們用來存放共享屬性和方法的。這些屬性和方法可以被實例對象引用。注意是引用,也就是自己沒有,指向那里去調用就行了。然后在這個對象里定義run方法

Person.prototype = {
   // properties and methods
   run: function() {
     console.log("I"m running");
   }
}

當然,我們這里只是為了多定義一個run方法,而不是定義整個prototype的對象(這樣會把這個對象的其他方法擦掉,只剩下run方法)。所以定義整個引用方法的方式就是
object.run = ... 即
Person.prototype.run = ...
這樣新創建的實例再也不用自己定義這個方法,只要從共享對象上引用就好了。舉例:

function Person(name) {
    this.name = name; // 屬性
    this.myfunction = function() {
        console.log("just work for me");
    }
}
Person.prototype.run = function (distance) {
    console.log("I"ve run " + distance + " meters");
}
var p1 = new Person("Pelemy");
var p2 = new Person("Summmy");
console.log(p1.name); // Pelemy
p1.run(100); // I"ve run 100 meters
console.log(p2.name); // Summy
p2.run(200); // I"ve run 200 meters

p1,p2的本身沒有run方法(構造函數里沒定義),但都能執行到,他們是引用prototype里的run方法。執行方法時,先在本地查找是否有這個方法,沒有則向上尋找prototype對象是否有,有則執行這個方法。這里可以通過hasOwnProperty方法來判斷本地是否有這個方法,沿用上面的例子

console.log(p1.hasOwnProperty("run")); // false
console.log(p1.hasOwnProperty("myfunction"); // true;
console.log(p1.hasOwnProperty("name"); // true;

把構造函數的定義視為本地屬性定義,把prototype屬性對象視為引用屬性定義,這樣分開來理解,就會輕松多了。

對象的引用對象與構造函數的prototype屬性的關系

實例對象創建后,構造函數中的屬性和方法成為本地屬性和方法,prototype中的屬性和方法成為引用屬性和方法。我想知道一個實例對象產生后,怎么知道這個對象是從哪里引用的?對象不像構造函數,生下來就有prototype屬性,連接著引用對象。但對象有一個只讀的屬性__proto__,指向的就是它的引用對象(這叫隱式原型對象)。這個對象和構造函數的prototype指向的是同一個對象。因為引用對象是放在那里供別人引用的,不會復制或重新產生,所以它是被直接定義到實例對象的__proto__的。

function Person(name) {
    this.name = name; // 屬性
}

var p = new Person();
console.log(p.__proto__ === Person.prototype); // true
prototype對象怎么產生

這個prototype對象是怎么來的呢?構造函數在JavaScript中產生時,隨即就有一個它的引用對象(prototype屬性指向的對象)產生了。它是伴隨著構造函數產生的。

延伸

prototype是構造函數生來就有的屬性,對象是沒有的。

構造函數的prototype屬性的值是一個對象。即Person.prototype是一個對象

prototype的屬性和方法是共用屬性和方法,是所有實例對象都有,不同的屬性和方法在構造函數實現,按這樣創建對象就是類的繼承的方式了。產生的實例對象相當于都從父類繼承過來,這就是為什么把引用的這個對象叫原型(不叫引用或共享)的原因了。

總結

構造函數中定義的屬性和方法是本地屬性和方法,prototype指向的對象定義的屬性和方法是引用屬性和方法。

prototype定義的屬性和方法能被實例共同引用,是共同的部分,相當于每個對象都有和引用對象同樣的屬性和方法,而自身的方法就通過構造函數來呈現。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/107654.html

相關文章

  • 深入理解JavaScript原型與繼承

    摘要:深入理解原型與繼承看過不少書籍,不少文章,對于原型與繼承的說明基本上讓人不明覺厲,特別是對于習慣了面向對象編程的人來說更難理解,這里我就給大家說說我的理解。 深入理解:JavaScript原型與繼承 看過不少書籍,不少文章,對于原型與繼承的說明基本上讓人不明覺厲,特別是對于習慣了面向對象編程的人來說更難理解,這里我就給大家說說我的理解。 首先JavaScript是一門基于原型編程的語言...

    mengbo 評論0 收藏0
  • 理解JavaScriptprototype和__proto__

    摘要:這篇文章的的目的試圖通過最簡單的表述讓大家理解和先把最重要的幾點列出來大家可以帶著這幾個核心要點閱讀下面的文章是用來在原型鏈上查找你需要的方法的實際對象所有的對象都有這個屬性這個屬性被引擎用作繼承使用根據的規范這個屬性應該是一個內在的屬性但 這篇文章的的目的試圖通過最簡單的表述,讓大家理解prototype和__proto__ 先把最重要的幾點列出來,大家可以帶著這幾個核心要點閱讀下面...

    tanglijun 評論0 收藏0
  • 深入理解Javascript原型關系

    摘要:如下所示在規范中,已經正式把屬性添加到規范中也可以通過設置和獲取對象的原型對象對象之間的關系可以用下圖來表示但規范主要介紹了如何利用構造函數去構建原型關系。 前言 在軟件工程中,代碼重用的模式極為重要,因為他們可以顯著地減少軟件開發的成本。在那些主流的基于類的語言(比如Java,C++)中都是通過繼承(extend)來實現代碼復用,同時類繼承引入了一套類型規范。而JavaScript是...

    ethernet 評論0 收藏0
  • Javascript面向對象編程

    摘要:如果要理解基于原型實現面向對象的思想,那么理解中得三個重要概念構造函數原型原型鏈對幫助理解基于原型的面向對象思想就顯得尤為重要。函數對象的原型在中,函數是一種特殊的對象,所有的函數都是構造函數的實例。 介紹 和java這種基于類(class-base)的面向對象的編程語言不同,javascript沒有類這樣的概念,但是javascript也是面向對象的語言,這種面向對象的方式成為 基...

    wanglu1209 評論0 收藏0
  • 理解 JavaScript call()/apply()/bind()

    摘要:理解文章中已經比較全面的分析了在中的指向問題,用一句話來總結就是的指向一定是在執行時決定的,指向被調用函數的對象。與和直接執行原函數不同的是,返回的是一個新函數。這個新函數包裹了原函數,并且綁定了的指向為傳入的。 理解 JavaScript this 文章中已經比較全面的分析了 this 在 JavaScript 中的指向問題,用一句話來總結就是:this 的指向一定是在執行時決定的,...

    duan199226 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<