原型對象和原型鏈

来源:https://www.cnblogs.com/yanmuxiao/archive/2018/03/14/8561914.html
-Advertisement-
Play Games

一、內置一級構造函數Object(首字母大寫) 普通函數: 1)、不建議使用new關鍵字調用,否則就成為構造函數的調用了; 2)、可以用return語句返回值; 3)、函數內部不建議使用this關鍵字,函數裡面的this指向window,添加在this身上的屬性是全局屬性; 4)、函數命名以駝峰方式 ...


一、內置一級構造函數Object(首字母大寫)

1、普通函數和構造函數的特點

普通函數:

  1)、不建議使用new關鍵字調用,否則就成為構造函數的調用了;
  2)、可以用return語句返回值;
  3)、函數內部不建議使用this關鍵字,函數裡面的this指向window,添加在this身上的屬性是全局屬性;
  4)、函數命名以駝峰方式,首字母小寫;

構造函數:

  1)、用new關鍵字調用,否則就成為普通函數的調用了;
  2)、函數內部可以使用this關鍵字
    在構造函數內部,this指向的是構造出的新對象。用this定義的變數或函數/方法,就是實例變數或實例函數/方法。需要用實例才能訪問到,不能用類型名訪問;
  3)、預設不用return返回值(或者說有預設的返回值,也就是當前對象)
  當然,我們也可以讓構造函數像普通函數一樣有返回值,但是返回值必須是引用類型對象,不能是值類型,如:null、undefined、boolean、number、string,否則這個返回值無效,依然返回構造的this對象。例如可以返回{a: 'A', b: 'B'}等等;
  4)、函數命名建議首字母大寫,與普通函數區分開
  不是命名規範中的,但是建議這麼寫。
  5)、每個構造函數都有一個原型對象,原型對象包含一個指向構造函數的引用。

2、Object構造函數
Object instanceof Object // true
Object instanceof Function // true
typeof Object // 'function'

 

Object既是對象,也是函數,我們稱這種對象為函數對象,是js內置的構造函數。所有的函數對象都有一個預設屬性為prototype(原型),這個屬性Object.prototype是一個對象,所以稱為原型對象,它的屬性集合有:

    console.log(Object.prototype);// 輸出如下:

    constructor:Object()
    __proto__: null
    hasOwnProperty

    __defineGetter__
    __defineSetter__
    __lookupGetter__
    __lookupSetter__
    isPrototypeOf
    propertyIsEnumerable
    toLocaleString
    toString
    valueOf
    get __proto__
    set __proto__

 

特別重要的三個屬性:

1)、Object.prototype.constructor是指向當前內置函數對象的引用。如下:

Object.prototype.constructor === Object // true

 

2)、Object.prototype.__proto__存放的是繼承關係,Object是一級函數對象,它沒有繼承與別的對象,所以它繼承的是空對象null。如下:

Object.prototype.__proto__ === null // true

 

3)、hasOwnProperty判斷對象的屬性是否為原型中的屬性。

 

二、內置二級構造函數Function(首字母大寫)

Function instanceof Object // true
Function instanceof Function // true
typeof Function // 'function'

 

1、Function是內置構造函數對象,所以有一個預設屬性為prototype,這個屬性Function.prototype是一個對象,它的屬性集合分別有:

constructor:Function()
__proto__: Object.prototype

// 繼承Object的屬性(方法) __defineGetter__ __defineSetter__ __lookupSetter__

 

Function.prototype.constructor是指向當前內置函數對象的引用,看:

Function.prototype.constructor === Function // true

js內置二級構造函數對象還有:

Date、Array、String、Boolean、RegExp、Number

用戶可以自定義的二級函數對象,如:

 var Person = new Function();

    // 也可以這樣(這隻是一種快捷方式):

    function Person() {}

    Person instanceof Object // true
    Person instanceof Function // true
    typeof Person // 'function'

 

還是那句話:所以的對象都是由函數創建的。

重點:

1、二級函數對象的原型對象都是繼承一級函數對象Object的原型對象,請看它們的原型指向:

Function.prototype.__proto__ === Object.prototype   // true
Date.prototype.__proto__ === Object.prototype   // true
Array.prototype.__proto__ === Object.prototype   // true
String.prototype.__proto__ === Object.prototype   // true
Boolean.prototype.__proto__ === Object.prototype   // true
RegExp.prototype.__proto__ === Object.prototype   // true
Number.prototype.__proto__ === Object.prototype   // true

Person.prototype.__proto__ === Object.prototype   // true

 

什麼情況下產生繼承關係呢?個人覺得用new運算符 + 構造函數才會產生繼承關係,但是這些二級構造函數對象都是js內置的,他們和Object的繼承關係真是不清楚,可能是太菜了........

2、二級對象繼承了一級對象Object.prototype中的所以屬性,同時二級對象也有自己的私有屬性,是Object的原型中沒有的,我們經常用到的比如:

a). Date的私有屬性
    getDate、getDay、getFullYear等等
b). String的私有屬性
    length、slice、concat、search等等
c). Array的私有屬性
    length、join、slice、splice等等

 

三、非函數對象(非內置函數對象的沒有內置的私有屬性)

1、常用的非函數對象,這種對象也稱為實例,這些對象都是new + 構造函數創建的,存在繼承關係

構造函數(函數對象),原型,實例之間的關係:每個構造函數都有一個原型對象,原型對象包含一個指向構造函數的引用,即constructor,而實例都包含一個指向原型對象的內部引用即proto

1)、var obj = {};(new Object())
2)、var arr = [];(new Array())
3)、var Num = new Number();
4)、var Str = new String();

 

2、非函數對象沒有原型,也就是沒有prototype屬性,但是非函數對象也是由函數創建的。既然它是由函數創建的,我們肯定能找到創建它的函數,如下:

a). json對象

var obj = new Object();// 很明顯可以看出有Object函數創建
obj.constructor === Object // true

b). 數組對象

var arr = new Array();
arr.constructor === Array // true

 

數組和對象還可以通過快捷方式創建,如:[]和{},實質上也是通過函數創建的,這種快捷方式叫做語法糖。請看:

var obj = {};
obj.constructor === Object // true

var arr = [];
arr.constructor === Array // true

 

總結:非函數對象都有constructor屬性指向創建該對象的函數。進一步說明對象都是由函數創建的。

3、非函數對象的繼承關係

1)、由2可以知道,非函數對象都是通過一級或者二級內置函數創建的,有contructor直接指向創建函數。那麼他們的繼承關係是怎樣的呢,是否有proto直接指向它繼承的對象?答案是當然有啦。在js中,只要你是一個對象,不是你繼承別的對象就是別的對象繼承你,我們叫這種通過原型對象繼承屬性的方式原型鏈。看:

a). json對象

var obj = {};
obj.__proto__ === Object.prototype // true
Object.prototype.__proto__ === null // true

// 這就是obj最長的原型鏈了
obj.__proto__.__proto__ === null // true

 

b). 數組對象

var arr = [];
arr.__proto__ === Array.prototype // true
Array.prototype.__proto__ === Object.prototype // true
Object.prototype.__proto__ === null // true

// 數組對象最長的原型鏈
arr.__proto__.__proto__.__proto__ === null // true

 

同理,其他非函數對象皆一樣。

2)、看一下非函數對象是否真的繼承了別的對象的屬性(方法)

a). 數組對象

var str = [1, 2, 3, 'a', 'b', 'c'];
str.slice(2, 5); // [3, "a", "b"]

結果很明顯,我們經常用就不多舉例了。

4、非函數對象的內置對象arguments

arguments只出現在函數中,偽數組,格式和數組一樣:[1, 2, 3],用於接收函數的參數。由Object創建,如下:

function arg() {

    console.log(arguments instanceof Object); // true
    console.log(arguments.constructor === Object); // true
    console.log(arguments.__proto__ === Object.prototype); // true

    console.log(typeof arguments.slice); // undefined
}

 

內置屬性length,可以通過索引訪問對應得值。它不是數組,不能用數組的方法。如:

arguments.slice(); // undefined

如何轉化為數組,從而可以使用數組的所以方法?

 // Array.prototype.slice.call(arguments);

    function arg() {

    var arguments = Array.prototype.slice.call(arguments);

    console.log(arguments instanceof Object); // true
    console.log(arguments.constructor === Object); // false
    console.log(arguments.__proto__ === Object.prototype); // false

    console.log(typeof arguments.slice); // 'function'
}

 

四、一級函數對象Object原型中的屬性hasOwnProperty

一級函數對象Object原型中的屬性hasOwnProperty會被所有的函數對象或者非函數對象繼承。

我們都知道對象是可以自定義屬性,如何判斷一個屬性是自定義的還是內置的或者繼承原型鏈中的呢?就看hasOwnProperty了本身了。

那麼我們哪些地方會用到hasOwnProperty。

1、判斷

var obj = {
        a: 'A',
        b: 'B'
};
obj.hasOwnProperty('toString'); // false(繼承的)
obj.hasOwnProperty('a'); // true (對象本身的)

 

2、遍歷

 Object.prototype.newProperty = 'newPropertyValue';
    var obj = {
        a: 'A',
        b: 'B'
    }
    for(var key in obj) {
        console.log(key + '==>' + obj[key])
    }

    // 結果:
    // a==>A
    // b==>B
    // newProperty==>newPropertyValue

    如何不遍歷newProperty呢?

    for(var key in obj) {
        if(obj.hasOwnProperty(key)) {
            console.log(key + '==>' + obj[key])
        }
    }
  // 結果:
   // a==>A
   // b==>B
 

 

五、總結

  1、對象的定義:若幹屬性(方法)的集合;

  2、所有的函數都是對象,但是對象不一定是函數,既是對象又是函數的對象稱為函數對象;

  3、所有的函數對象都有一個預設屬性為prototype,這個屬性prototype是一個對象。其中有一個屬性為constructor,這個屬性是當前函數的引用;另外一個是__proto__屬性,指明繼承關係。

  4、所有的非函數對象(實例)都有一個constructor屬性,這個屬性是一個存放著創建該對象的函數;同時也有__proto__屬性,指明繼承關係。

  5、由第3、4點可以說明:所有的對象(函數對象和非函數對象)都是由函數創建的。

  6、什麼是原型對象?

  每一個函數對象都有的一個prototype屬性,這個屬性是一個對象,叫原型對象。只有函數(對象)才有原型,才能被繼承。

  7、什麼是原型鏈(也叫原型對象鏈)?

  用來繼承屬性(方法)的一條(原型)對象鏈。


  (js任何一個對象不是被繼承就是繼承別的對象,所以js對象總能找到一條屬於它的用來繼承屬性(方法)的(原型)對象鏈。)

 

很多地方都參考了別的文章,但是都忘了出處,就不列舉了......,有錯歡迎指出!

 


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

-Advertisement-
Play Games
更多相關文章
  • textView用於顯示文本,大量文字顯示在一起顯得過於緊湊。可通過在佈局中更改TextView屬性設置行間距。 1、android:lineSpacingMultiplier="1.5" 表示1.5倍行距 2、android:lineSpacingExtra="3dp" 表示行間距離為3dp 有時 ...
  • 作者:ManfredHu 鏈接:http://www.manfredhu.com/2018/03/15/31-laya-game-tips/index.html 聲明:版權所有,轉載請保留本段信息,謝謝大家 LayaBox Web前端最近都在跨界!!現在又伸手到游戲領域了。但是真的那麼好跨界嗎?請讓 ...
  • 之前在看對象的api中for in函數時,有一個地方讓我略有疑惑: 為什麼是obj[key]而不是obj.key呢?我們在瀏覽器試一下: 說起來也有點尷尬,原來在for in函數中,得到的key是一個字元串類型,所以只能用obj[key],其實,比如說在這個對象中,obj.x和obj["x"]是完全 ...
  • 前言:這是筆者學習之後自己的理解與整理。如果有錯誤或者疑問的地方,請大家指正,我會持續更新! AJAX 是 asynchronous javascript and XML 的簡寫,就是非同步的 javascript 和 XML。這一技術能夠向伺服器請求額外的數據而無須刷新整個頁面,會帶來更好的用戶體驗 ...
  • 1. ng-init 屬性: 2. ng-selected 屬性: <html><head></head><body> <!--<input type="text" ng-model="good.factory" title="{{good.factory}}">--> <select class= ...
  • 一、什麼是Promise Promise是對象,代表了一個函數最終可能的返回值或拋出的異常,就是用來非同步處理值的。 Promise是一個構造函數,自己身上有all、reject、resolve這幾個非同步方式處理值的方法,原型上有then、catch等同樣很眼熟的方法。 二、為什麼使用Promise ...
  • localstorage 是 HTML5 提供的在客戶端存儲數據的新方法,主要作用是將數據保存在客戶端中,並且數據是永久保存的,除非人為干預刪除。 localstorage 的局限 1、只有版本較高的瀏覽器中才支持 localstorage2、localStorage的值的類型限定為string類型 ...
  • 一.冒泡排序 原理:簡單來說就是相鄰兩個元素進行對比,按照你需要的排序方式(升序or降序)進行位置替換,替換時需要額外一個變數當作中間變數去暫存值。 總結步驟: 1、外迴圈是遍歷每個元素,每次都放置好一個元素; 2、內迴圈是比較相鄰的兩個元素,把大/小的元素交換到後面; 3、等到第一步中迴圈好了以後 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...