1、JS 如何使屬性或者對(duì)象不能被改變?
1)對(duì)象常量
結(jié)合writable: false和configurable: false就可以創(chuàng)建一個(gè)真正的常量屬性(不可修改、重定義或者刪除)。

2)禁止擴(kuò)展
如果想要禁止一個(gè)對(duì)象添加新屬性并且保留已有屬性,可以使用Object.preventExtensions()。

3)密封
Object.seal()會(huì)創(chuàng)建一個(gè)“密封”的對(duì)象,實(shí)際上是會(huì)在一個(gè)現(xiàn)有對(duì)象上調(diào)用Object.preventExtensions(…)并把所有現(xiàn)有屬性標(biāo)記為configurable: false。所以,密封后不僅不能添加新屬性,也不能重新配置或者刪除任何現(xiàn)有屬性(但是可以修改屬性的值)。

4)凍結(jié)
Object.freeze()會(huì)創(chuàng)建一個(gè)凍結(jié)對(duì)象,實(shí)際上會(huì)在一個(gè)現(xiàn)有對(duì)象上調(diào)用Object.seal(…)并把所有“數(shù)據(jù)訪問”屬性標(biāo)記為writable: false,這樣就無法修改它們的值了。
最后,注意一點(diǎn),所有方法創(chuàng)建的都是淺不變性。就是說,它們只會(huì)影響目標(biāo)對(duì)象和它的直接屬性,如果目標(biāo)對(duì)象引用了其他對(duì)象(數(shù)組、對(duì)象、函數(shù)等),其他對(duì)象的內(nèi)容不受影響,仍然可變。

2、!=、== 、!==、===的用法和區(qū)別
== 和 != 比較若類型不同,先償試轉(zhuǎn)換類型,再作值比較,最后返回值比較結(jié)果 ;
=== 和 !== 只有在相同類型下,才會(huì)比較其值。(值和類型都相同的情況下比較);
==, 兩邊值類型不同的時(shí)候,要先進(jìn)行類型轉(zhuǎn)換,再比較;
===,不做類型轉(zhuǎn)換,類型不同的一定不等。

3、function a(){} 和 var a = function(){}的區(qū)別
當(dāng)我們使用a方法的時(shí)候,是沒有問題的,如果使用b方法,會(huì)報(bào)一個(gè)undefined錯(cuò)誤。
這是因?yàn)椋?b>function a()方法已經(jīng)被提前加載好了,所以a方法存在。var b會(huì)被提升,但是并沒有聲明賦值,方法必須是腳本執(zhí)行到相應(yīng)位置,才會(huì)被加載,所以提前使用b方法會(huì)報(bào)undefined錯(cuò)誤。

4、function的length屬性
function的length屬性表示該函數(shù)的形參個(gè)數(shù)。
因?yàn)閒unction它是一個(gè)對(duì)象,所以這個(gè)length屬性可以往它的原型找,但是function的原型length值理所當(dāng)然的為0。因?yàn)?b>函數(shù)的形參個(gè)數(shù)是定義函數(shù)時(shí)才定的。
Function這個(gè)構(gòu)造器本身也是一個(gè)函數(shù),它接受至少一個(gè)參數(shù),這個(gè)參數(shù)是定義函數(shù)后的函數(shù)體。
function的arguments的length屬性。arguments它表示函數(shù)傳入實(shí)際參數(shù)的個(gè)數(shù)。

5、JS 中封裝、繼承及多態(tài)實(shí)現(xiàn)
1)封裝
封裝是指把客觀事物封裝成抽象的類,并且類可以把自己的數(shù)據(jù)(屬性)和對(duì)數(shù)據(jù)的操作(方法)只讓可信的類或者對(duì)象操作,對(duì)不可信的進(jìn)行信息隱藏。
2)繼承
繼承是指可以讓某個(gè)類型的對(duì)象獲得另一個(gè)類型的對(duì)象的屬性的方法。它可以使用現(xiàn)有類的所有功能,并在無需重新編寫原來的類的情況下對(duì)這些功能進(jìn)行擴(kuò)展。 通過繼承創(chuàng)建的新類稱為“子類”,被繼承的類稱為“基類”、或“父類”。
我們常見的繼承有:
a、原型繼承:直接讓子類的原型對(duì)象指向父類實(shí)例,當(dāng)子類實(shí)例找不到對(duì)應(yīng)的屬性和方法時(shí),就會(huì)往它的原型對(duì)象,也就是父類實(shí)例上找,從而實(shí)現(xiàn)對(duì)父類的屬性和方法的繼承。屬于引用類型傳值,引用副本實(shí)例屬性的修改必然會(huì)引起其他副本實(shí)例屬性的修改。
b、call繼承:構(gòu)造函數(shù)繼承,即在子類的構(gòu)造函數(shù)中執(zhí)行父類的構(gòu)造函數(shù),并為其綁定子類的this,讓父類的構(gòu)造函數(shù)把成員屬性和方法都掛到子類的this上去。繼承不到父類原型上的屬性和方法。
c、組合式繼承:原型繼承+call繼承。在子類的構(gòu)造函數(shù)中通過Parent.call(this)繼承父類的屬性,然后改變子類的原型為new Parent()來繼承父類的函數(shù)。創(chuàng)建子類實(shí)例都會(huì)執(zhí)行了兩次構(gòu)造函數(shù)(Parent.call()和new Parent()),雖然這并不影響對(duì)父類的繼承,但子類創(chuàng)建實(shí)例時(shí),原型中會(huì)存在兩份相同的屬性和方法。
d、寄生組合式繼承:為了解決每次創(chuàng)建子類實(shí)例都執(zhí)行了兩次構(gòu)造函數(shù)的問題,私有的只拿私有的,用call來做。共有只拿共有的,用Object.create()來做。
e、es6 extends 繼承:通過關(guān)鍵字extends實(shí)現(xiàn)子類繼承父類的私有和公有,這里需要注意如果子類里面寫了constructor,就必須寫super否則會(huì)報(bào)錯(cuò)。
3)多態(tài)
多態(tài)是指一個(gè)類實(shí)例的相同方法在不同情形有不同表現(xiàn)形式。多態(tài)機(jī)制使具有不同內(nèi)部結(jié)構(gòu)的對(duì)象可以共享相同的外部接口。
a、函數(shù)重載(overload):指在同一作用域內(nèi),可以有一組具有相同函數(shù)名,不同參數(shù)列表的函數(shù)。
JS函數(shù)不支持多態(tài),但是事實(shí)上JS函數(shù)是無態(tài)的,支持任意長(zhǎng)度,類型的參數(shù)列表。如果同時(shí)定義了多個(gè)同名函數(shù),則以最后一個(gè)函數(shù)為準(zhǔn)。
js通過函數(shù)名找到對(duì)應(yīng)的函數(shù)對(duì)象;然后根據(jù)函數(shù)按照定義時(shí)的參數(shù),和表達(dá)式參數(shù)列表按順序匹配,多余的參數(shù)舍去,不夠的參數(shù)按undefined處理;然后執(zhí)行函數(shù)代碼。
b、函數(shù)覆寫(override):方法名相同,后者覆蓋前者。