前端面試題系列之-原生js篇

隱式類型轉(zhuǎn)換相關(guān)

字符串連接符與算數(shù)運算符

  • 字符串連接符+:會把其他數(shù)據(jù)類型調(diào)用String()方法轉(zhuǎn)換成字符串然后拼接
  • 算數(shù)運算符+:會把其他數(shù)據(jù)類型調(diào)用Number()方法轉(zhuǎn)換成數(shù)字然后做加法計算

關(guān)系運算符

關(guān)系運算符會把其他數(shù)據(jù)轉(zhuǎn)換成number之后再比較

  • 一個為字符串另一個為數(shù)字惋鹅,則將字符串轉(zhuǎn)換成數(shù)字比較
  • 兩個都為字符串則依次比較兩個的charCodeAt()值
  • undefined與null互相比較為相等,與其他類型比較為不等
  • NaN與任何數(shù)據(jù)都不等
  • 復雜數(shù)據(jù)類型會先調(diào)用valueOf()再調(diào)用toString()轉(zhuǎn)換成字符串殉簸,然后再轉(zhuǎn)換成number

邏輯非運算符

  • 有邏輯非運算符的會將數(shù)據(jù)轉(zhuǎn)換成布爾類型
  • 除了0闰集、-0返十、NaN洞坑、undefined迟杂、null侧漓、""监氢、false以外都為true

各類型隱式轉(zhuǎn)換規(guī)則

  • String:變量 + 字符串
  • Number:變量 + 自增自減運算符纵揍,算術(shù)運算符泽谨,關(guān)系運算符
  • Boolean:變量 + 邏輯非運算符

字符串類型轉(zhuǎn)為數(shù)值類型:

  • 字符串任意位置出現(xiàn)任意非數(shù)字吧雹、非空格的字符雄卷,均轉(zhuǎn)為NaN
  • 數(shù)字中間存在空格,轉(zhuǎn)為NaN

閉包相關(guān)

什么是閉包

閉包就是一個函數(shù)鳄炉,這個函數(shù)能夠訪問其他函數(shù)的作用域中的變量拂盯。

優(yōu)點

  • 封裝變量谈竿,模仿塊級作用域

缺點

  • this指向問題
  • 內(nèi)存泄漏問題
  • 變量發(fā)生變化問題

作用域和變量提升相關(guān)

作用域

作用域分為全局作用域、函數(shù)作用域及塊級作用域

變量提升

js在執(zhí)行一個作用域的代碼之前呀洲,會先將變量聲明及函數(shù)聲明提到整個作用域頂部兵罢,隨后依次執(zhí)行代碼卖词,其中若變量與函數(shù)同名此蜈,函數(shù)優(yōu)先級要高于變量。
即:

  • 將變量聲明與函數(shù)聲明提到作用域頂部
  • 函數(shù)聲明優(yōu)先級高于變量聲明
  • 依次執(zhí)行代碼

作用域鏈

如果當前作用域中找不到變量,則會想上層作用域查找抛蚁,依次往上查找瞧甩,形成作用域鏈

NaN是什么肚逸?有什么特別之處朦促?

NaN 是 not a number 的縮寫务冕,代表非數(shù)字值的特殊值,該屬性用于指示某個值不是數(shù)字箩退,是一個全局對象的屬性
特別之處:

  • NaN 屬性的初始值就是 NaN,和 Number.NaN 的值一樣
  • 在現(xiàn)代瀏覽器中(ES5)喊括,NaN是一個不可配置(non-configurable)府喳,不可寫(non-writable)的屬性.但是在ES3中,這個屬性的值是可以更改的申窘,但是也應該避免覆蓋
  • 編碼中很少直接用到 NaN 碎捺,通常都是計算失敗的時候,作為Math的某個方法的返回值出現(xiàn)(例如:Math.sqrt(-1))诵叁,或者嘗試將一個字符串解析成為數(shù)字拧额,但是失敗了的時候(parseInt("blabla"))
  • NaN和任何值比較,都不相等捎拯,包括它自己NaN是number類型 typeof NaN //'number'

== 和 === 的區(qū)別

兩等是值判斷,會調(diào)用隱式類型轉(zhuǎn)換建芙,不判斷類型
三等是值判斷加類型判斷右蒲,判斷兩個值是否嚴格相等

typeof和instanceof的區(qū)別

typeof

用于判斷數(shù)據(jù)類型瑰妄,返回值為6個字符串,分別為string竹宋、Boolean莫矗、number、function、object、undefined。其中null會返回object結(jié)果

instanceof

instanceof用來判斷對象搂橙,判斷方法是根據(jù)對象的原型鏈依次向下查詢

js的數(shù)據(jù)類型有哪些

JS原生有5種簡單數(shù)據(jù)類型:Undefined版扩,Null悼尾,BooleanNumberString。還有一個復雜數(shù)據(jù)類型Object烹骨。 函數(shù)在JS中是對象拉宗,而不是一種數(shù)據(jù)類型

undefined和null的區(qū)別

Undefined類型為變量聲明了但是沒有初始化(var box),而Null表示一個空對象引用(var box = null)肾扰。注意:未初始化的變量和賦值為 null 的 變量會相等偷拔,可通過typeof或者使用三等進行判斷

call、apply、bind的區(qū)別

call 和 apply 是為了改變函數(shù)體內(nèi)部 this 的指向踏枣。對于 apply躬厌、call 二者而言,作用完全一樣匙奴,只是接受參數(shù)的方式不太一樣啦租。bind()最簡單的用法是創(chuàng)建一個函數(shù),使這個函數(shù)不論怎么調(diào)用都有同樣的this值。

示例:

function func(arg1, arg2) {};

func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2])
var obj = {
    a: 123,
};
 
var foo = {
    getV: function(k) {
        return this.a + k;
    }
}
 
console.log(foo.getV.bind(obj, 1)());  //124
console.log(foo.getV.call(obj, 1));    //124
console.log(foo.getV.apply(obj, [1]));   //124

區(qū)別:

  • 傳參不同举农,調(diào)用不同。bind 是返回對應函數(shù),便于稍后調(diào)用勺像;apply 涩维、call 則是立即調(diào)用 。

js的假值有哪些

0-0NaNundefined蚕泽、null荒吏、""锡宋、false

js面向?qū)ο笈c原型、原型鏈相關(guān)

參考鏈接

原型(對象屬性)

Javascript規(guī)定显拜,每個函數(shù)都有一個prototype對象屬性矮台。只有函數(shù)才有prototype屬性蛤迎。指向另一個對象(原型鏈上面的)。prototype(對象屬性)的所有屬性和方法,都會被構(gòu)造的實例繼承。這意味著,我們可以把那些不變的屬性和方法,直接定義在prototype對象屬性上。

prototype就是調(diào)用構(gòu)造函數(shù)所創(chuàng)建的那個實例對象的原型(proto)侦高。

prototype可以讓所有對象實例共享它所包含的屬性和方法。也就是說匙握,不必在構(gòu)造函數(shù)中定義對象信息蛾娶,而是可以直接將這些信息添加到原型中蛔琅。

原型鏈 (JS原型與原型鏈繼承)

實例對象與原型之間的連接,叫做原型鏈。proto( 隱式連接 )
JS在創(chuàng)建對象的時候切距,都有一個叫做proto的內(nèi)置屬性话肖,用于指向創(chuàng)建它的函數(shù)對象的原型對象prototype最筒。
內(nèi)部原型(proto)和構(gòu)造器的原型(prototype)
1蔚叨、每個對象都有一個proto屬性,原型鏈上的對象正是依靠這個屬性連結(jié)在一起
2、作為一個對象丹擎,當你訪問其中的一個屬性或方法的時候,如果這個對象中沒有這個 方法或?qū)傩贼岢澹敲碕avascript引擎將會訪問這個對象的proto屬性所指向上一個對 象,并在那個對象中查找指定的方法或?qū)傩耘迸绻荒苷业皆等Γ蔷蜁^續(xù)通過那個對象 的proto屬性指向的對象進行向上查找袜蚕,直到這個鏈表結(jié)束糟把。

淺談constructor

在 Javascript 語言中,constructor 屬性是專門為 function 而設(shè)計的牲剃,它存在于每一個 function 的prototype 屬性中遣疯。這個 constructor 保存了指向 function 的一個引用。

__proto__

JS 在創(chuàng)建對象(不論是普通對象還是函數(shù)對象)的時候凿傅,都有一個叫做 __proto__ 的內(nèi)置屬性缠犀,用于指向創(chuàng)建它的構(gòu)造函數(shù)的原型對象。

    var obj = []
    console.log(obj.__proto__ === Array.prototype)  //true

示例題

    function Foo() {}
    var f1 = new Foo()

請回答以下問題:

  1. f1.__proto__ ===
  2. f1.constructor ===
  3. f1.prototype ===
  4. Foo.__proto__ ===
  5. Foo.prototype ===
  6. Foo.constructor ===
  7. Foo.prototype.constructor ===
  8. Foo.prototype.__proto__ ===

繼承的幾種寫法及優(yōu)缺點

JS繼承的實現(xiàn)方式

this指向相關(guān)

  • this 永遠指向函數(shù)運行時所在的對象聪舒,而不是函數(shù)被創(chuàng)建時所在的對象辨液。
  • this的指向在函數(shù)定義的時候是確定不了的,只有函數(shù)執(zhí)行的時候才能確定this到底指向誰箱残,實際上this的最終指向的是那個調(diào)用它的對象

js new一個對象都經(jīng)過了什么

new對象:

function Person(name, age) {
  this.name = name;
  this.age = age;
}
var person = new Person("Alice", 23);

new一個對象的四個過程:1滔迈、創(chuàng)建一個空對象?

var obj = new Object();

2、讓Person中的this指向obj,并執(zhí)行Person的函數(shù)體?

var result = Person.call(obj);

3亡鼠、設(shè)置原型鏈,將obj的proto成員指向了Person函數(shù)對象的prototype成員對象?

obj.__proto__ = Person.prototype;

4敷待、判斷Person的返回值類型间涵,如果是值類型,返回obj榜揖。如果是引用類型勾哩,就返回這個引用類型的對象。

if (typeof(result) == "object")
  person = result;
else
  person = obj;

宏任務和微任務

  • 宿主環(huán)境提供的叫宏任務举哟,宿主環(huán)境包括瀏覽器和node
  • 宏任務有:
    • script
    • setTimeout
    • setInterval
    • setImmediate
    • requestAnimationFrame
    • I/O
    • UI渲染
  • 由語言標準提供的叫微任務思劳,即由語言標準(ECMA)提供的就是微任務,比如ES6提供的promise妨猩。
  • 微任務有
    • process.nextTick
    • MutationObserver
    • Promise

執(zhí)行過程

  • js引擎將代碼按照類別分到宏任務和微任務隊列中
  • 執(zhí)行宏任務潜叛,執(zhí)行完成,清空微任務隊列
  • 執(zhí)行下一個宏任務壶硅,執(zhí)行完成后威兜,清空微任務隊列
  • 依次執(zhí)行宏任務隊列的下一個宏任務,執(zhí)行完成后庐椒,清空微任務隊列

怎樣理解setTimeout 執(zhí)行誤差

如果當前 執(zhí)行棧 所花費的時間大于 定時器 時間椒舵,那么定時器的回調(diào)在 宏任務(macrotask) 里,來不及去調(diào)用约谈,所以這個時間會有誤差笔宿。

如何實現(xiàn)深淺拷貝

淺拷貝

// 1. ...實現(xiàn)
let copy1 = {...{x:1}}
// 2. Object.assign實現(xiàn)
let copy2 = Object.assign({}, {x:1})
// 數(shù)組采用slice、concat方法

深拷貝

// 1. JOSN.stringify()/JSON.parse()
let obj = {a: 1, b: {x: 3}}
JSON.parse(JSON.stringify(obj))

// 2. 遞歸拷貝
function deepClone(obj) {
  let copy = obj instanceof Array ? [] : {}
  for (let i in obj) {
    if (obj.hasOwnProperty(i)) {
      copy[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]
    }
  }
  return copy
}

JSON.stringify()的缺點

  • 會忽略 undefined
  • 會忽略 symbol
  • 不能序列化函數(shù)
  • 不能解決循環(huán)引用的對象
  • 不能正確處理new Date()
  • 不能處理正則

數(shù)組去重的幾種寫法

let list = [1, 2, 3, 4, 5, 2, 2, 2, 7, 6, 4, 8, 1];
// 創(chuàng)建新數(shù)組棱诱,判斷數(shù)據(jù)是否在新數(shù)組中
function arrToRepeat1(arr) {
    let repeatList = [];
    list.forEach(value => {
        if (!repeatList.includes(value)) repeatList.push(value);
    })
    return repeatList;
}
console.log(arrToRepeat1(list));
// 創(chuàng)建新數(shù)組泼橘,通過下標判斷是否是重復的值
function arrToRepeat2(arr) {
    let repeatList = [];
    list.forEach((value, index) => {
        // 左側(cè)的為第一個值的索引,右側(cè)為重復的當前的值的索引
        if (arr.indexOf(value) === index) repeatList.push(value);
    })
    return repeatList;
}
console.log(arrToRepeat2(list));
// 使用set集合
console.log([...new Set(list)]);

數(shù)組排序的問題

默認數(shù)組排數(shù)函數(shù)sort有問題军俊,不指定排序方法時侥加,元素會按照轉(zhuǎn)換為的字符串的諸個字符的Unicode位點進行排序

常用解決方法


list.sort((a, b) => a - b) // 從小到大
list.sort((a, b) => b - a) // 從大到小

數(shù)組降維

array = array.reduce((acc, val) => acc.concat(val), []);  // 一層扁平化
array = [].concat(...array);  // 一層扁平化
array = array.flat();  // 一層扁平化

手寫防抖和節(jié)流

js垃圾回收機制,怎么理解js中的內(nèi)存泄露

垃圾回收機制

垃圾回收是釋放已經(jīng)不再需要的變量等,來減少系統(tǒng)所占用的內(nèi)存。

標記清除法

工作原理:
當變量進入環(huán)境時(例如在函數(shù)中聲明一個變量)腥光,將這個變量標記為“進入環(huán)境”砾省,當變量離開環(huán)境時,則將其標記為“離開環(huán)境”伏蚊。標記“離開環(huán)境”的就回收內(nèi)存。
工作流程:

  • 垃圾收集器會在運行的時候會給存儲在內(nèi)存中的所有變量都加上標記。
  • 去掉環(huán)境中的變量以及被環(huán)境中的變量引用的變量的標記狈网。
  • 那些還存在標記的變量被視為準備刪除的變量。
  • 最后垃圾收集器會執(zhí)行最后一步內(nèi)存清除的工作,銷毀那些帶標記的值并回收它們所占用的內(nèi)存空間拓哺。
引用計數(shù)法

跟蹤記錄每個值的引用次數(shù)(值)
流程:

  • 聲明一個變量勇垛,并給這個變量賦值,這個值的引用次數(shù)就是1
  • 同一個值被賦給另一個變量士鸥,這個值的引用次數(shù)+1
  • 變量的值被更改了 那原本那個值的引用次數(shù)-1
  • 引用次數(shù)為0時闲孤,說明沒辦法訪問這個值了
  • 垃圾收集器下一次運行時,會釋放引用次數(shù)為0的值所占的內(nèi)存

缺點:循環(huán)引用將不能被自動回收烤礁。

內(nèi)存泄漏

內(nèi)存泄漏是由于疏忽或錯誤造成程序未能釋放那些已經(jīng)不再使用的內(nèi)存讼积,造成內(nèi)存的浪費。

引起內(nèi)存泄漏的情況
  • 意外的全局變量
  • 被遺忘的定時器和定時器的回調(diào)函數(shù)
  • 閉包
  • 循環(huán)引用問題
  • 沒有清理的DOM元素引用

DOM事件模型是什么

事件處理的幾種寫法

移動端的touch事件

事件委托/事件代理

target脚仔、currentTarget的區(qū)別勤众?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市鲤脏,隨后出現(xiàn)的幾起案子们颜,更是在濱河造成了極大的恐慌,老刑警劉巖猎醇,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掌桩,死亡現(xiàn)場離奇詭異,居然都是意外死亡姑食,警方通過查閱死者的電腦和手機波岛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來音半,“玉大人则拷,你說我怎么就攤上這事〔莛” “怎么了煌茬?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長彻桃。 經(jīng)常有香客問我坛善,道長,這世上最難降的妖魔是什么邻眷? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任眠屎,我火速辦了婚禮,結(jié)果婚禮上肆饶,老公的妹妹穿的比我還像新娘改衩。我一直安慰自己,他們只是感情好驯镊,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布葫督。 她就那樣靜靜地躺著竭鞍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪橄镜。 梳的紋絲不亂的頭發(fā)上偎快,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音洽胶,去河邊找鬼滨砍。 笑死,一個胖子當著我的面吹牛妖异,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播领追,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼他膳,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了绒窑?” 一聲冷哼從身側(cè)響起棕孙,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎些膨,沒想到半個月后蟀俊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡订雾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年肢预,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片洼哎。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡烫映,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出噩峦,到底是詐尸還是另有隱情锭沟,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布识补,位于F島的核電站族淮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏凭涂。R本人自食惡果不足惜祝辣,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望切油。 院中可真熱鬧较幌,春花似錦、人聲如沸白翻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至岛琼,卻和暖如春底循,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背槐瑞。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工熙涤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人困檩。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓祠挫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親悼沿。 傳聞我的和親對象是個殘疾皇子等舔,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355