摘要:使用構造函數創建對象后,新對象與構造函數沒有關系了,新對象的屬性指向的是構造函數的原型對象。構造繼承使用父類的構造函數來增強子類的實例,等于是在子類的構造函數內部執行。
一.js原始類型:
在js中,存在著6種原始值:
* boolean * number * string * undefined * null * symbol
注意: 雖然typeof null輸出的是object,但是null并不是object類型,因為早期的bug;
number類型是浮點數類型,所以才會有js精度問題出現。0.1+0.2 !== 0.3。 原始類型存儲的都是值,是沒有函數可以調用的。
symbol類型: symbol類型的對象永遠不相等,即便創建他們的時候傳入了相同的值,可以借助此特性解決屬性名的沖突問題。
for...in..拿不到symbol類型的屬性值,而且要用[]的方式來讀取symbol類型的屬性值,用點的方式讀不到。
在js中,除了原始類型其他的就是對象類型了。
Q1:對象類型和原始類型的不同之處?
答:對象類型和原始類型不同的是,原始類型存貯的是值,對象那個類型存儲的是地址(指針)。當創建了一個對象類型的時候,計算機回在內存 中開辟一個空間賴存放值,但是我們需要找到這個空間,這個控件會擁有一個地址(指針)。當我們將變量賦值給另外一個變量時,復制的是原本變量的地址(指針)。
Q2:函數參數是對象會發生什么?
答:函數參數是對象的話,在函數內部可能會改變這個參數對象,生成新對象。三.typeof VS instanceof
Q1:typeof是否能正確判斷類型?
答:對于原始類型來說,typeof除了null都可以正確顯示類型,typeof null顯示的是object是錯誤的。對于其他的,除了function會返回function,其他都會返回object。
Q2. instanceof能正確判斷對象的原理是什么?
答:instanceof內部機制是通過原型鏈來判斷對象類型的。 eg: const Person = function () {} const p1 = new Person() p1 instanceof Person // true var str = "hello world" str instanceof String // false四.類型轉換:
1.轉Boolean: 在條件判斷時,除了undefined,null,0,-0,NaN,"",false,其他所有值都轉化為true,包括所有對象。
2.對象轉原始類型: 對象在轉換類型的時候,會調用內置的[[ToPrimitive]]函數,對于該函數來說,
算法邏輯一般來說如下: * 如果已經是原始類型了,就不需要換磚了 * 調用x.valueof(),如果轉換為基礎類型,就返回轉換的值 * 調用x.toString(),如果轉化為基礎類型,就返回轉換的值 * 如果都沒有返回原始類型,就會報錯 1)四則運算符: 加法運算符特點: *運算中如果一方為字符串,那么就會把另一方葉轉換為字符串,1 + "1" // "11" *如果一方不是字符串或者數字,那么會將它轉化為數字或者字符串:true+ true // 2 ; 4 + [1,2,3] // "41,2,3" 注意: + "a"是快速將"a"轉化成number類型的寫法;"a" + + "b" // "aNaN" 那么對于除了加法運算符其他運算符來說,只要一方是數字,那么另一方就會被轉化為數字。反正最終都是要轉化為數字來運算。 4 * "3" // 12 4 * [] // 0 4 * [1,2] // NaN 2)比較運算符 大于小于運算都會轉化為數字進行運算。 關于 ==: *undefined 等于 null *字符串和數字比較時,字符串轉數字 *數字和布爾類型比較時,布爾轉數字 *字符串和布爾比較時,兩者轉數字五.this
this永遠指向最后調用它的那個對象。
1.改變this指向:
* 使用es6箭頭函數 * 在函數內部使用 _this = this * 使用 apply,call,bind * new 實例化一個對象
2.箭頭函數: 箭頭函數的this始終指向函數定義時的this,而非執行時(意味著如果箭頭函數被非箭頭函數包含,this綁定的就是最近一層非箭頭函數的this)。
箭頭函數中沒有this綁定,必須通過查找作用域鏈來決定其值。
3.apply,call,bind區別
apply和call只是傳入的參數不同。call接受的是若干個參數列表,而apply接受的是一個包含多個參數的數組。
bind和apply,call區別:
bind創建了一個新的函數,需要手動去調用它;六.new的過程:
創建一個空對象obj;
將新創建的空對象的隱式原型指向其構造函數的顯示原型;
使用call改變this的指向;
如果無返回值或者返回一個非對象值,則將obj返回作為新對象;如果返回值時一個新對象的華那么直接返回該對象。
七. == VS ===Q1: ==和 === 有什么區別?
答: 對于 == 來說,如果雙方的類型不一樣的華,就會進行類型轉換。 流程: * 首先判斷兩者類型是否相同 * 判斷是否為 undefined == null //true * string轉number比較 * boolean轉number比較 * object轉原始類型比較 但是,=== 的比較只需要判斷兩者類型和值是否相同。八.閉包:
Q1: 什么是閉包?
答:函數A內部有一個函數B,函數B可以訪問到函數A中的變量,那么函數B就是閉包。
Q2:經典面試題:循環中使用閉包解決var定義函數的問題:
答:第一種:使用閉包的方式: for (var i = 1; i <=5 ; i++) { ;(function(j) { setTimeout(function timer() { console.log(j) }, j * 1000) })(i)}
第二種:用let定義的方式: for (let i=1 ; i <=5 ; i++) { setTimeout(function timer() { console.log(i) }, i * 1000) } Q3:閉包的優缺點? 閉包作用(優點):可以讀取到函數內部的變量,可以讓這些變量的值始終保持在內存中,不會被垃圾回收掉。
閉包缺點:因為閉包會使得函數中變量保存在內存中,所以會增大內存使用量,使用不當很容易造成內存泄漏。浪費內存。
清除閉包:退出函數之前,將不使用的局部變量刪除。
1.堆和棧:棧(stack)為自動分配的內存空間,它由系統自動釋放;而堆(heap)則是動態分配的內存,大小不定也不會自動釋放。
2.基本數據類型存放在棧中,數據大小確定,內存空間大小可以分配,是直接按值存放的,所以可以直接訪問。基本類型的比較是值的比較。
3.引用類型存放在堆中,變量實際上存放的是棧1內存的指針,引用類型的值可變。引用類型的比較是引用的比較。所以比較兩個引用類型,是看其的引用是否指向同一個對象。
Q1.淺拷貝?
答:淺拷貝只復制一層對象的屬性,并不包括對象里面的為引用類型的數據。
Q2.深拷貝?
答: 深拷貝遞歸復制了對象的所有層級屬性。
Q3.深拷貝,淺拷貝以及賦值的區別?
答:淺拷貝,深拷貝和原數據都不是指向同一對象,而賦值對象和原對象是指向同一對象。 第一層數據為基本類型,改變會使原數據改變,深拷貝以及淺拷貝不會。 原數據中包含子對象,改變子對象會使賦值對象以及淺拷貝對象改變,不會使深拷貝對象改變。
Q4.如何實現淺拷貝?
答:1.可以通過Object.assign來解決。(Object.assign()方法用于將所有可枚舉的值從一個或多個源對象復制到目標對象。它將返回目標對象。) eg: let a={ age: 1 } let b=O bject.assign({}, a) a.age=2 console.log(b.age) // 1 2.可以通過展開運算符...來實現淺拷貝 eg: let a={ age: 1} let b={ ...a } a.age=2 console.log(b.age) // 1
Q5.如何實現深拷貝?
答:1.該問題可以通過JSON.parse(JSON.stringify(object))來解決。 eg: let a={age: 1, jobs: { first: "FE" } } let b=J SON.parse(JSON.stringify(a)) a.jobs.first="native" console.log(b.jobs.first) // FE 但是該方法也是有局限性的: * 會忽略undefined * 會忽略symbol * 不能序列化函數 * 不能解決循環引用的對象十:原型和原型鏈:
js是基于原型的繼承。
1.使用構造函數創建對象后,新對象與構造函數沒有關系了,新對象的[[prototype]]屬性指向的是構造函數的原型對象。
2.構造函數、原型和實例的關系:
* 構造函數都有一個屬性prototype,這個屬性是一個對象(Object的實例) * 原型對象里面有個constractor屬性,該屬性指向原型對象所屬的構造函數。當原型對象被修改過,constractor就不一定指向原來的構造函數了。 * 實例對象都有一個_proto_屬性,該屬性也指向構造函數的原型對象,它是一個非標準屬性,不可以用于編程,它用于瀏覽器自己使用。
3.prototype和_proto_的關系:
* prototype是構造函數的屬性; * _proto_是實例對象的屬性; * 這兩者都會指向同一個對象。 總結:*函數也是對象,對象不一定是函數; * 對象的本質:無序的鍵值對集合,鍵值對當中的值可以是任意數據類型的值; *對象就是一個容器,這個容器當中放的是屬性和方法。
4.原型鏈:
原型鏈就是可以理解為有限的實例對象和原型之間組成的有限鏈,就是用來實現屬性共享和繼承的。
5.屬性搜索:
* 在訪問對象的某個成員的時候在對象中查找是否存在; * 如果當前對象中沒有就在構造函數的原型對象中查找; * 如果原型對象中沒有就在原型對象的原型上找; * 直到找到Object的原型對象的原型是null為止。 eg: var arr = [] 原型鏈:arr -> Array.prototype -> Object.prototype -> null
Q1:什么是原型?
答: 原型也是一個對象,并且這個對象中包含了很多函數。原型的constract屬性指向構造函數,構造函數又通過prototype屬性指回原型,到那時并不是所有函數都具有這個屬性。十一:js繼承:
1.原型鏈繼承:將父類的實例作為子類的原型。
eg:Cat.prototype = new Animal() 缺點:子類無法給父類傳參,子類要新增屬性和方法的話,必須要在new Parent()這樣的語句之后執行,否則會被覆蓋。
2.構造繼承:使用父類的構造函數來增強子類的實例,等于是在子類的構造函數內部執行Parent.call(this)。
eg:function Cat(name) { Animal.call(this); this.name = name || "Tom"; } var cat = new Cat(); 缺點:沒有原型,每次創建一個子類實例都要執行一遍Parent函數。
3.組合式繼承:結合原型鏈繼承和構造繼承,組合式繼承在使用過程中會被調用兩次:一次是創建子類的時候,一次是在子類構造函數的內部。
eg: function Cat(name){ Animal.call(this); this.name = name || "Tom"; } Cat.prototype = new Animal();
3.class繼承:
class繼承的核心在于使用extends表明繼承自哪個父類,并且在子類構造函數中必須調用super,因為這段代碼可以看成Parent.call(this,value). eg: class Parent { constructor(value) { this.val = value } getValue() { console.log(this.val) } } class Child extends Parent { constructor(value) { super(value) this.val = value } } let child = new Child(1) child.getValue() // 1 child instanceof Parent // true十二:var、let及const區別:
1.var和let區別:
* let有塊級作用域的說法,也就是let聲明的變量只能在這個塊內部使用,別的地方不能使用。var聲明的變量可以在全局使用,var在函數內部聲明的變量只能在函數內部使用。 * let沒有變量提升,var有變量提升 * let聲明的變量存在“暫時性死區”,而var聲明的變量沒有 * let不允許在同一個快內重復聲明一個變量。因此也不能在函數內部重復聲明一個變量。 * var聲明的變量會掛載到window上,而let聲明的對象不會掛載到window上。
const特性:
const聲明一個只讀的常量。一旦聲明,常量的值就不能改變;
const聲明的變量必須初始化,不然會報錯;
const聲明的變量也存在暫時性死區;
const聲明的變量只在所聲明的塊級作用域內有效;
const聲明的常量也與let一樣不可重復聲明。
Q1.什么是提升?
答:就是變量可以在神明之前使用,并且值為undefined。
Q2. 什么是暫時性死區?
答:在let命令聲明之前,該變量都素hi不可用的。十三.模塊化:
Q1.為什么要使用模塊化?
答:使用模塊化可以帶來以下好處: * 解決命名沖突; * 提供復用性; * 提高代碼可維護性。
Q2.實現模塊化的方式?
CommonJS AMD CMD
1.require/exports:
遵循CommonJS/AMD,只能在運行時確定模塊的依賴關系及輸入/輸出的變量,無法進行靜態優化。
2.import/export:
遵循ES6規范,支持編譯時靜態分析,便于JS引入宏和類型檢驗,動態綁定。十四、JS異步編程:
1. 并發(concurrency)和并行(parallelism)區別: Q1:并發與并行的區別? 答:并發是宏觀概念,我分別有任務A和任務B,在一段時間內通過任務間的切換完成了這個任務。 并行是微觀概念,假設CPU中存在兩個核心,那么我就可以同時完成任務A和任務B。同時完成多個任務的情況可以稱之為并行。 2.回調函數(callback): Q1.什么是回調函數? 答:ajax(url,() => { //處理邏輯; }) Q2.回調函數有什么缺點? 答:1)回調函數有一個致命的弱點就是容易寫出回調地獄(callback hell)。 eg: ajax(url, () => { // 處理邏輯 ajax(url1, () => { // 處理邏輯 ajax(url2, () => { // 處理邏輯 }) }) }) 回調地獄根本問題: * 嵌套函數存在耦合性,一旦有所改動,就會牽一發而動全身; * 嵌套函數一多,就很難處理錯誤。 2)回調函數不能使用trycatch捕獲錯誤,不能直接return。 Q3.如何解決“地獄回調”? 答:* function拆解 * promise * generater * async/await 3. Generator: 4. promise: Q1:Promise的特點? 答:對象的狀態不受外界影響,只有三種狀態:pending resolved rejected 狀態一旦改變,就不會再變,任何時候都可以得到這個結果。 Q2. Promise的優缺點? 答:缺點:* promise無法取消,一旦新建就會立即執行,無法中途取消; * 如果不設置回調函數,promise內部會拋出錯誤,不會反映到外部; * 當處于pending狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)。 優點:可以解決回調地獄問題。 Q3. 什么是Promise鏈? 答:就是在Promise構造函數里面通過then來一步一步使用promise,因為then方法返回的也是一個全新的promise實例。 Q4. Promise構造函數執行和then函數執行有什么區別? 答:then方法每次都返回一個promise實例。 5. Async/Await: Q1.async的特點? 答:一個函數如果加上async,那么該函數就會返回一個promise。async就是將函數返回值使用Promise.resolve()包裹了一下,和then中處理返回值一樣,并且await只能配套在async函數內部使用。 Q2.優缺點? 答: 優點:處理then的調用鏈能夠更清晰的寫出代碼,并且能夠優雅的解決回調地獄問題。 缺點:因為await將一部代碼改造成了同步代碼,如果多個異步代碼沒有依賴性卻使用了await會導致性能上的降低。 Q3.await原理是什么? 答:await內部實現了generator。 實現async/await: async function doIt() { console.time("doIt"); const time1 = 300; const time2 = await step1(time1); const time3 = await step2(time2); const result = await step3(time3); console.log(`result is ${result}`); console.timeEnd("doIt"); } doIt(); 6.常用定時器函數: setTimeout() setInterval() requestAnimationFrame() requestAnimationFrame自帶函數節流功能,基本可以保證在16.6毫秒內只執行一次,并且該函數的延時效果是精準的。如果有循環定時器的需求,requestAnimationFrame是最好的選擇。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/102454.html
摘要:為什么狀態需要經過最大報文段生存時間才能返回到狀態雖然按道理,四個報文都發送完畢,我們可以直接進入狀態了,但是我們必須假象網絡是不可靠的,有可以最后一個丟失。所以狀態就是用來重發可能丟失的報文。 1、TCP的三次握手和四次揮手 1.1 三次握手: 客戶端請求 -> 服務器響應 -> 客戶端確認收到響應,建立連接(保證網絡正常) showImg(https://segmentfault....
摘要:某個請求任務耗時嚴重,不會影響到其它連接的正常執行如何實現長連接 1、sleep函數該如何實現的 sleep函數,將程序執行掛起一段時間,阻塞程序的運行 ES6方案: function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function test() { con...
摘要:先說下我面試情況,我一共面試了家公司。篇在我面試的眾多公司里,只有同城的面問到相關問題,其他公司壓根沒問。我自己回答的是自己開發組件面臨的問題。完全不用擔心對方到時候打電話核對的問題。 2019的5月9號,離發工資還有1天的時候,我的領導親切把我叫到辦公室跟我說:阿郭,我們公司要倒閉了,錢是沒有的啦,為了不耽誤你,你趕緊出去找工作吧。聽到這話,我虎軀一震,這已經是第2個月沒工資了。 公...
本文是公眾號讀者jianfeng投稿的面試經驗恭喜該同學成功轉型目錄:毅然轉型,沒頭蒼蠅制定目標,系統學習面試經歷毅然轉崗,沒頭蒼蠅首先,介紹一下我的背景。本人坐標廣州,2016年畢業于一個普通二本大學,曾經在某機構培訓過Android。2018年初的時候已經在兩家小公司工作干了兩年的android開發,然后會一些Tomcat、Servlet之類的技術,當時的年薪大概也就15萬這樣子。由于個人發展...
閱讀 3986·2021-11-23 10:09
閱讀 1347·2021-11-23 09:51
閱讀 2946·2021-11-23 09:51
閱讀 1595·2021-09-07 09:59
閱讀 2359·2019-08-30 15:55
閱讀 2306·2019-08-30 15:55
閱讀 2956·2019-08-30 15:52
閱讀 2568·2019-08-26 17:04