javascript --- 原型初探七日談

来源:http://www.cnblogs.com/beyond-succeed/archive/2016/08/29/5819328.html
-Advertisement-
Play Games

在javascript中,像原型,閉包這樣的概念,只要我們能領悟其中的原理,一切都會顯得格外清晰與明瞭。 原型屬性(prototype): 下麵我們簡單定義一個函數 在這些函數一定義就被賦予的屬性中,就包括prototype屬性,她的初始化是一個空對象: 當然我們也可以自己添加該屬性: 而且我們可以 ...


javascript中,像原型,閉包這樣的概念,只要我們能領悟其中的原理,一切都會顯得格外清晰與明瞭。

原型屬性(prototype):

下麵我們簡單定義一個函數

function her(a, b){
    return a + b;
}

在這些函數一定義就被賦予的屬性中,就包括prototype屬性,她的初始化是一個空對象:

typeof her.prototype  // Object

當然我們也可以自己添加該屬性:

her.prototype = {};

而且我們可以賦予這個空對象一些屬性和方法,這並不會對foo函數產生神馬影響,以為只有her()函數被當做構造函數來使用的情況下,這些屬性才起作用。

來個例子:

function her(){
  this.name = 'Anna',
  this.child = 'Jok',
  this.say = function(){
       return 'My name is' + this.name + 'My child is' + this.child;
  }
}

上面是一個簡單的構造函數,我們就用構造器屬性prototype屬性來增加她的屬性和方法,您可以這樣:

her.prototype.sex = 'women';
her.prototype.height = '175cm';
her.prototype.doing = function(){
    return 'I is a' + this.sex + 'I am height is' + this.height;
}

使用原型的屬性和方法:

var she = new her();
she.name;  // Anna
she.child; // Jok

如上所講如果想用以上的屬性和方法,那必須new一個上述構造函數her()的一個對象實例。

對於原型來說,最重要的一點就是理解她的‘實時性’,由於在javascript中幾乎所有對象都是通過引用的方式傳遞的。因此我們創建出來的新對象並沒有屬於自己的原型副本。這也就意味著我們可以隨時修改prototype的屬性和方法,並且由同一構造函數創建出來所有對象的prototype都會同時改變。 (甚至還會影響到修改之前就已經創建好的對象)。

繼續之前的例子:

her.prototype.eat = 'water';
she.eat; // water

哪怕she之前就被創建了,我仍然還會在這個對象中訪問到eat屬性。

自身屬性與原型屬性

上述的創建doing()方法那個示例,其實直接引用一次her.prototype也可以完成上述工作:

function her(){
  this.name = 'Anna',
  this.child = 'Jok',
  this.say = function(){
       return 'My name is' + this.name + 'My child is' + this.child;
  },
  this.sex = 'women',
  this.eat = 'water'  
}
her.prototype.doing = function(){
    return 'I is a' + her.prototype.sex + 'I am height is' + her.prototype.height;
}

這樣有神馬不同嗎?要想知道這個問題就必須深入瞭解原型的工作原理。

var she = new her();

當我們訪問she對象的某個屬性時,例如she.name時,javascript引擎會遍歷該對象的所有屬性,並查找出name屬性,如果找到了就會直接返回,否則為undefined.

這回我們訪問she.sex會發生神馬呢,javascript引擎依舊會查詢she的所有屬性,但是這回找不到一個叫sex的屬性了,接下來javascript引擎就會去查找用於創建該對象的構造函數的原型(等價於我們直接訪問到she.constructor.prototype),如果在原型中找到了該屬性,就立刻使用該屬性。

這種方式與直接訪問原型屬性是一樣的。每個對象都有屬於自己的構造器屬性,這個屬性引用的就是創建該對象的構造函數,所以:

she.constructor === her; // true
she.constructor.prototype.sex; // women

現在,我們回顧一下整個過程。我們知道每個對象都有一個構造器,而原型本身也是一個對象,必然也會有自己的構造器,而這個構造器又會有自己的原型。於是這種結構會一直持續下去,並取決於原型鏈的長度。她們的最後一環必然是Object()內建對象,她是最高級的父及對象(始祖)。

she.toString();  // Object

利用自身屬性重寫原型屬性

通過上述我們知道一個對象自身屬性中沒有找到指定的屬性,前提是這個屬性存在,那麼她就會順著原型鏈去找。但是遇到對象的自身的屬性和原型屬性重名怎麼辦呢?

答案是自身屬性的優先順序要高於原型屬性(自己的利益至上)。

來個梨子:

function her(){
   this.name = 'Anna';
}
var she = new her();
she.name = 'Lous';
she.name;  // Lous

我們可以通過hasOwnProperty()方法來判斷一個屬性是自身屬性還是來自於原型屬性。

she.hasOwnProperty('name'); // true

如果這時候我們把自身屬性刪掉,那麼同名的原型屬性又會浮出水面:

delete she.name;  //true
she.name // Anna
she.hasOwnProtype('name') // false

當然我們可以重建這個屬性:

she.name = 'Lous';
she.name; // Lous;
she.hasOwnProtype('name'); // true

如何判斷一個屬性到底是原型鏈中那個原型的屬性呢?答案還是用hasOwnProperty()屬性。例如我們想知道toString()這個方法來自與哪裡:

she.hasOwnProperty('toString');  // false
she.constructor.hasOwnProperty('toString');  // false
she.constructor.prototype.hasOwnProperty('toString');  // false
Object.hasOwnProperty('toString');  // false
Object.prototype.hasOwnProperty('toString');  // true

呵呵(*Φ皿Φ*)!!

對象的枚舉屬性

如果想要獲得一個對象的所有屬性的列表,那麼就用for-in迴圈吧!(for迴圈適合數組,for-in迴圈更適合對象),來個慄子:

var params = {
    name : 'Anna',
    sex : 'women'    
}

var url = 'http://www.baidu.com?',
      i,
      query = [];
for(i in params){
    query.push(i + '=' + params[i]);
}
url += query.join('&');  // 'http://www.baidu.com?name=Anna&sex:women';

在這裡有幾個細節需要註意:

  1. 不適所有的對象屬性都是可以枚舉的,例如length,constructor等就不會被顯示,那些會顯示的屬性被稱為可枚舉的,我們可以通過各個對象所提供的propertyIsEnumerable()方法來判斷對象的某個屬性是不是可枚舉的。

  2. 原型鏈中的各個屬性也會被顯示出來,當然她們是被可枚舉的。

 來個慄子:

function her(){
    this.name = 'Anna';
    this.sex = 'women';
    this.say = function(){'My name is' + this.name;}
}
var she = new her();
she.eat = 'water';

for(var i in she){
    console.log(i + '=' + she[i]);
}

name = 'Anna'
sex = 'women'
say = function(){'My name is' + this.name;}
eat = 'water'

我們再來一次,這次輸出自身屬性

for(var i in she){
    if(she.hasOwnProperty(i)){
        console.log(i +'='+she[i]);
    }
}

name = 'Anna'
sex = 'women'
say = function(){'My name is' + this.name}

未完待續。。。。。。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一,定義和用法 所有瀏覽器都支持 <a> 標簽。 <a> 標簽定義超鏈接,用於從一張頁面鏈接到另一張頁面。 <a> 元素最重要的屬性是 href 屬性,它指示鏈接的目標。 在所有瀏覽器中,鏈接的預設外觀是: 未被訪問的鏈接帶有下劃線而且是藍色的 已被訪問的鏈接帶有下劃線而且是紫色的 活動鏈接帶有下劃 ...
  • 一些簡單的字元串操作,歡迎大家參考學習。 ...
  • 這段代碼的效果具體是輸入標題和內容,點擊發佈把消息發佈出去,並使最新的消息始終在內容的最上面,代碼為: 這段代碼主要運用了一些DOM節點操作的知識,純屬學習之餘練手作品,大家可以參考參考。 ...
  • 具體效果我是仿照hao123導航頁面圖片輪播的效果,大家可以去那個網站參考 ...
  • 這種效果的具體效果是滑鼠移上去滾動停止,移出滾動,滾動時是一張一張圖片的滾動,即滾動一張之後停2s開始滾動下一張,具體內容請大家參考代碼。 ...
  • 這種效果的主要思想是圖片內容部分的寬度要遠遠大於要展示區域的寬度,使其出現滾動條。複製上一組圖片的內容使其在效果上實現無縫滾動,具體的請大家參考代碼。 ...
  • 寫一個方法,讓"1234"變成迴文數字“1234321”,就是順著讀和倒著讀都是一樣的;註:不讓用reverse()方法; function palindrome(str){ var arr = str.split(""); var arr1 = []; for (var i = arr.lengt ...
  • 前面有分享過改變層級的輪播圖演算法,今天繼續利用透明度來實現無位移的輪播圖演算法。 實現邏輯:將所有要輪播的圖片全部定位到一起,即一層一層摞起來,並且利用層級的屬性調整正確的圖片順序,將圖片的透明度全部設置為0,然後在讓初始的第一張圖片的透明度為1即可,具體演算法如下: <!DOCTYPE html><h ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...