原型與原型鏈

原型與原型鏈

全局對象window

ECMAScript 規(guī)定全局對象叫做 global,但是瀏覽器把 window 作為全局對象
這些全局變量分為兩種:

  1. 一種是 ECMAScript 規(guī)定的
    • global.parseInt
    • global.parseFloat
    • global.Number
    • global.String
    • global.Boolean
    • global.Object
  2. 一種是瀏覽器自己加的屬性
    • window.alert
    • window.prompt
    • window.confirm
    • window.console.log
    • window.console.dir
    • window.document
    • window.document.createElement
    • window.document.getElementById
      注:瀏覽器自己加的屬性,window對象中的所有方法都可以省去window;例如 window.alert()可以直接寫 alert();正是因為是瀏覽器自己加的屬性,所以不同瀏覽器所呈現(xiàn)的效果也會不同。

簡單類型與對象的區(qū)別

聲明一個變量

//聲明簡單的數(shù)據(jù)類型
var n1 = 1;
//聲明一個對象,可以用n2.toString()將其轉(zhuǎn)換成字符串
var n2 = new Number(1);
IMG_0208.JPG

通過內(nèi)存圖可以看出他們在內(nèi)存中的儲存方式是不同的,n1是直接聲明簡單的數(shù)據(jù)類型(number),存儲在stack棧內(nèi)存中,而n2是聲明了一個對象stack內(nèi)存中存儲著該對象的內(nèi)存地址,對象的內(nèi)容存儲在heap堆內(nèi)存中。但是我們平時常用的寫法卻是第一種!也可以直接調(diào)用valueOf() 方法 和toSting()方法,原因是:臨時轉(zhuǎn)換(用完就回收),如果你使用n1的寫法,調(diào)用了了如valueOf方法,那么JS會創(chuàng)建一個臨時的對象,然后調(diào)用該對象的方法,調(diào)用結束后臨時對象就會被垃圾回收掉。

常見踩坑題

var n =1;
n.xxx = 2;
//n.xxx = 2;會報錯嗎?
//n.xxx的值是多少?

答案:n.xxx = 2;這句話不會報錯,執(zhí)行這句話時,JS會創(chuàng)建一個臨時對象,為臨時對象添加屬性,執(zhí)行這句話后,臨時對象就會被回收,如果再執(zhí)行n.xxx,結果是undefined,因為給n添加完屬性后臨時對象就會被回收,n本質(zhì)上還是一個數(shù)值,沒有臨時對象,再去重新創(chuàng)建一個新的對象,里面沒有這個屬性(有個這屬性的對象已經(jīng)被刪了)。

Number對象

  • Number.valueOf() //獲取對象本身的值
  • Number.toString() //將數(shù)值轉(zhuǎn)化為字符串
  • Number.toFixed() //將其轉(zhuǎn)換為小數(shù)
  • Number.toExponential() //將其轉(zhuǎn)化為科學計數(shù)法

String對象

  • String.charAt() //獲取字符串中某一位的字符
  • String.charCodeAt() //獲取字符串中某一位的字符的Unicode編碼
  • String.trim() //刪除字符串中多余的空格
  • String1.concat(String2) //連接字符串1和字符串2
  • String.slice(start,end) //切片,截取字符串(包前不包后),從start到end
  • String.replace(‘e’,’o’) //將字符串中的e替換成o(只能替換第一次出現(xiàn)的字符)
  • String.indexOf() //搜索字符串中的內(nèi)容(只檢測到第一次出現(xiàn)的字符),沒搜到返回-1
  • String.split() //分隔
  • String.substr(start[, length]) //截取,返回一個字符串中從指定位置開始到指定字符數(shù)的字符

Boolean對象

image.png

注:f1和f2的值都是false,但是f2是對象,一切對象(不論是否是空對象)都是truey,所以使用if判斷語句,會將f2轉(zhuǎn)化為了true,打印出2。

Object對象

Object對象,兩種賦值方法是一樣的,沒有任何區(qū)別。但是

var obj1 = {};
var obj2 = {};
obj1 === obj2; // false

為什么obj1不恒等于obj2???因為它們在stack棧內(nèi)存中存儲的內(nèi)容是heap堆內(nèi)存中的地址,每個對象的內(nèi)容在heap內(nèi)存中的地址是不會一樣的,所以對象與對象一般都是不相等的。(除非你將一個對象的內(nèi)存地址復制給另一個對象)。

原型鏈

所有對象都有 toString 和 valueOf 屬性,但是不需要給每個對象一個 toString 和 valueOf。因為JS每次聲明一個對象都要寫一次這些方法這樣寫的話會非常占用內(nèi)存,JS 的做法是把所有的對象共用的屬性全部放在heap堆內(nèi)存的一個對象(共用屬性組成的對象),然后讓每一個對象的proto存儲這個「共用屬性組成的對象」的地址。而這個共用屬性,就是傳說中的原型

image.png

1.proto就是這些共用屬性的引用。
2.聲明Number對象、String對象、Boolean對象時,如聲明Number對象,在stack棧內(nèi)存中存儲著該對象的內(nèi)存地址,對象的內(nèi)容存儲在heap堆內(nèi)存中。對象的內(nèi)容里面有proto,它指向的Number的共用屬性(Number.prototype)。

一些推導等式

通過var 對象 = new 函數(shù);推出其他燒腦的等式

var n = new Number(1);
//var 對象 = new 函數(shù);

//對象的__proto__最終指向某對象的共用屬性,構造某對象的函數(shù)的prototype也指向某對象的共用屬性
//__proto__ 是對象的屬性,prototype是函數(shù)的屬性
對象.__proto__ === 函數(shù).prototype

//函數(shù)的prototype是對象,這個對象對應的就是最簡單的函數(shù)Object
函數(shù).prototype.__proto__ === Object.prototype

//由于函數(shù)本身即是函數(shù)(最優(yōu)先被視為函數(shù)),也是對象,而函數(shù)的構造函數(shù)是Function
函數(shù).__proto__ === Function.prototype

//Function即是對象,也是函數(shù),但他優(yōu)先是個函數(shù)
Function.__proto__ === Function.prototype

//Function.prototype也是對象,是普通的對象,所以其對應的函數(shù)是Object
Function.prototype.__proto__=== Object.prototype

我們經(jīng)過上面的推導,發(fā)現(xiàn)Function,他即是函數(shù),也是對象,所以他有函數(shù)的prototype,也有對象的proto,即Function.prototype 與Function.proto互相引用。
注:Object.proto === Function.prototype,因為 Function 是 Object 的構造函數(shù)。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容