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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...