原型與原型鏈
全局對象window
ECMAScript 規(guī)定全局對象叫做 global,但是瀏覽器把 window 作為全局對象
這些全局變量分為兩種:
- 一種是 ECMAScript 規(guī)定的
- global.parseInt
- global.parseFloat
- global.Number
- global.String
- global.Boolean
- global.Object
- 一種是瀏覽器自己加的屬性
- 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);
通過內(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對象

注: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存儲這個「共用屬性組成的對象」的地址。而這個共用屬性,就是傳說中的原型

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ù)。