精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Javascript面試的完美指南(開發者視角)

開發 前端
這些是 JavaScrip t中的基本概念。正如我最初提到的,除了工作經驗和知識之外,準備有助理于你通過 JavaScript 面試。始終保持學習。留意最新的發展(第六章)。深入了解JavaScript的各個方面,如 V6 引擎、測試等。最后,沒有掌握數據結構和算法的面試是不成功的。

Javascript面試的***指南(開發者視角)

為了說明 JS 面試的復雜性,首先,請嘗試給出以下結果:

  1. onsole.log(2.0 == “2” == new Boolean(true) == “1”) 

十有八九的會給出false, 其實運行結果是true,原因請看 這里

1) 理解 JS 函數

函數是 JavaScript 的精華,是 JS 一等公民。JS 函數不僅僅是一個普通的函數,與其他語言不同,JS 函數可以賦值給變量,作為參數傳遞給另一個函數,也可以從另一個函數返回。

  1. console.log(square(5));  
  2. /* ... */  
  3. function square(n) { return n * n; }  

以為代碼很簡單,大家應該都知道會打印:25。接著看一個:

  1. console.log(square(5));  
  2. var square = function(n) {  
  3. return n * n;  
  4.  

乍一看,你可能會忍不住說也打印了 25。但很不幸,會報錯:

  1. TypeError: square is not a function 

在 JavaScript 中,如果將函數定義為變量,變量名將被提升,是 JS 執行到它的定義才能被訪問。

你可能在一些代碼中頻繁的見到如下代碼。

  1. var simpleLibrary = function() { 
  2.    var simpleLibrary = { 
  3.         a, 
  4.         b, 
  5.         addfunction(a, b) { 
  6.             return a + b; 
  7.         }, 
  8.         subtract: function(a, b) { 
  9.             return a - b;    
  10.         } 
  11.    } 
  12.   return simpleLibrary; 
  13. }();  

為什么會做這種奇怪的事情? 這是因為一個函數變量中變量和函數被分裝,可以避免全局變量污染。 JQuery 到Lodash 的庫采用這種技術提供 $、_ 等

2) 理解 bind、apply 和 call

你可能在所有常用庫中看到過這三個函數。它們允許局部套用, 我們可以把功能組合到不同的函數。一個優秀的js開發者可以隨時告訴你關于這三個函數。

基本上,這些是改變行為以實現某些功能的原型方法,根據 JS 開發人員 Chad 的說法,用法如下:

希望使用某個上下文調用該函數,請使用 .bind() ,這在事件中很有用。 如果要立即調用函數,請使用.call() 或 .apply(),并修改上下文。

舉例說明

讓我們看看上面的陳述是什么意思! 假設你的數學老師要求你創建一個庫并提交。你寫了一個抽象的庫,它可以求出圓的面積和周長:

  1. var mathLib = { 
  2.     pi: 3.14, 
  3.     area: function(r) { 
  4.         return this.pi * r * r; 
  5.     }, 
  6.     circumference: function(r) { 
  7.         return 2 * this.pi * r; 
  8.     } 
  9. };  

提交后,老師調用了它:

  1. mathLib.area(2);  
  2. 12.56  

老師發現他給你要求是 pi 精確到小數點后 5 位數而你只精確到 2 位, 現在由于***期限已過你沒有機會提交庫。 這里 JS的 call 函數可以幫你, 只需要調用你的代碼如下:

  1. mathLib.area.call({pi: 3.1.159}, 2) 

它會動態地獲取新的 pi 值,結果如下:

  1. 12.56636 

這時,注意到 call 函數具有兩個參數:

  • Context
  • 函數參數

在 area 函數中, 上下文是對象被關鍵詞 this 代替,后面的參數作為函數參數被傳遞。 如下: 

  1. var cylinder = { 
  2.     pi: 3.14, 
  3.     volume: function(r, h) { 
  4.         return this.pi * r * r * h; 
  5.     } 
  6. };  

調用方式如下: 

  1. cylinder.volume.call({pi: 3.14159}, 2, 6); 
  2. 75.39815999999999  

Apply 類似,只是函數參數作為數組傳遞。 

  1. cylinder.volume.apply({pi: 3.14159}, [2, 6]);  
  2. 75.39815999999999 

如果你會使用 call 你基本就會用 apply 了,反之亦然, 那 bind 的用法又是如何呢 ?

bind 將一個全新的 this 注入到指定的函數上,改變 this 的指向, 使用 bind 時,函數不會像 call 或 apply 立即執行。 

  1. var newVolume = cylinder.volume.bind({pi: 3.14159});  
  2. newVolume(2,6); // Now pi is 3.14159  

bind 用途是什么?它允許我們將上下文注入一個函數,該函數返回一個具有更新上下文的新函數。這意味著這個變量將是用戶提供的變量,這在處理 JavaScript 事件時非常有用。

3) 理解 js 作用域(閉包)

JavaScript 的作用域是一個潘多拉盒子。從這一個簡單的概念中,就可以構造出數百個難回答的面試問題。有三種作用域:

  • 全局作用域
  • 本地/函數作用域
  • 塊級作用域(ES6引進)

全局作用域事例如下:

  1. x = 10; 
  2. function Foo() { 
  3.   console.log(x); // Prints 10 
  4. Foo()  

函數作用域生效當你定義一個局部變量時:

  1. pi = 3.14; 
  2. function circumference(radius) {     
  3.      pi = 3.14159; 
  4.      console.log(2 * pi * radius); // 打印 "12.56636" 不是 "12.56" 
  5. circumference(2);  

ES16 標準引入了新的塊作用域,它將變量的作用域限制為給定的括號塊。

  1. var a = 10;  
  2. function Foo() { 
  3.   if (true) { 
  4.     let a = 4; 
  5.   } 
  6.  
  7.   alert(a); // alerts '10' because the 'let' keyword 
  8. Foo();  

函數和條件都被視為塊。以上例子應該彈出 4,因為 if 已執行。但 是ES6 銷毀了塊級變量的作用域,作用域進入全局。

現在來到神奇的作用域,可以使用閉包來實現,JavaScript 閉包是一個返回另一個函數的函數。

如果有人問你這個問題,編寫一個輸入一個字符串并逐次返回字符。 如果給出了新字符串,則應該替換舊字符串,類似簡單的一個生成器。

  1. function generator(input) { 
  2.   var index = 0; 
  3.   return { 
  4.     nextfunction() { 
  5.       if (index < input.lenght) { 
  6.         return input[index -1]; 
  7.       } 
  8.       return ""
  9.     } 
  10.   } 
  11.  

執行如下:

  1. var mygenerator = generator("boomerang");  
  2. mygenerator.next(); // returns "b"  
  3. mygenerator.next() // returns "o"  
  4. mygenerator = generator("toon");  
  5. mygenerator.next(); // returns "t" 

在這里,作用域扮演著重要的角色。閉包是返回另一個函數并攜帶數據的函數。上面的字符串生成器適用于閉包。index 在多個函數調用之間保留,定義的內部函數可以訪問在父函數中定義的變量。這是一個不同的作用域。如果在第二級函數中再定義一個函數,它可以訪問所有父級變量。

4) this (全局域、函數域、對象域)

在 JavaScript 中,我們總是用函數和對象編寫代碼, 如果使用瀏覽器,則在全局上下文中它引用 window 對象。 我的意思是,如果你現在打開瀏覽器控制臺并輸入以下代碼,輸出結果為 true。

  1. this === window; 

當程序的上下文和作用域發生變化時,this 也會發生相應的變化。現在觀察 this 在一個局部上下文中:

  1. function Foo(){ 
  2.   console.log(this.a); 
  3. var food = {a: "Magical this"}; 
  4. Foo.call(food); // food is this 

思考一下,以下輸出的是什么:

  1. function Foo(){  
  2. console.log(this); // 打印 {}?  
  3.  

因為這是一個全局對象,記住,無論父作用域是什么,它都將由子作用域繼承。打印出來是 window 對象。上面討論的三個方法實際上用于設置這個對象。

現在,this 的***一個類型,在對象中的 this, 如下:

  1. var person = { 
  2.     name"Stranger"
  3.     age: 24, 
  4.     get identity() { 
  5.         return {who: this.name, howOld: this.age}; 
  6.     } 
  7.  

上述使用了 getter 語法,這是一個可以作為變量調用的函數。

  1. person.identity; // returns {who: "Stranger", howOld: 24} 

此時,this 實際上是指對象本身。正如我們前面提到的,它在不同的地方有不同的表現。

5) 理解對象 (Object.freeze, Object.seal)

通常對象的格式如下: 

  1. var marks = {physics: 98, maths:95, chemistry: 91}; 

它是一個存儲鍵、值對的映射。 javascript 對象有一個特殊的屬性,可以將任何東西存儲為一個值。這意味著我們可以將一個列表、另一個對象、一個函數等存儲為一個值。

可以用如下方式來創建對象:

  1. var marks = {};  
  2. var marks = new Object();  

可以使用 JSON.stringify() 將一個對象轉制成字符串,也可以用 JSON.parse 在將其轉成對象。 

  1. // returns "{"physics":98,"maths":95,"chemistry":91}"  
  2. JSON.stringify(marks);  
  3. // Get object from string  
  4. JSON.parse('{"physics":98,"maths":95,"chemistry":91}');  

使用 Object.keys 迭代對象:

  1. var highScere = 0;  
  2. for (i of Object.keys(marks)) { 
  3.   if (marks[i] > highScore) 
  4.     highScore = marks[i]; 
  5.  

Object.values 以數組的方式返回對象的值。

對象上的其他重要函數有:

  • Object.prototype(object)
  • Object.freeze(function)
  • Object.seal(function)

Object.prototype 上提供了許多應用上相關的函數,如下:

Object.prototype.hasOwnProperty 用于檢查給定的屬性/鍵是否存在于對象中。 

  1. marks.hasOwnProperty("physics"); // returns true  
  2. marks.hasOwnProperty("greek"); // returns false  

Object.prototype.instanceof 判斷給定對象是否是特定原型的類型。

  1. function Car(make, model, year) { 
  2.   this.make = make; 
  3.   this.model = model; 
  4.   this.year = year
  5. var newCar = new Car('Honda''City', 2007); 
  6. console.log(newCar instanceof Car); // returns true  

使用 Object.freeze 可以凍結對象,以便不能修改對象現有屬性。 

  1. var marks = {physics: 98, maths:95, chemistry: 91};  
  2. finalizedMarks = Object.freeze(marks);  
  3. finalizedMarks["physics"] = 86; // throws error in strict mode  
  4. console.log(marks); // {physics: 98, maths: 95, chemistry: 91}  

在這里,試圖修改凍結后的 physics 的值,但 JavaScript不允許這樣做。我們可以使用 Object.isFrozen 來判斷,給定對象是否被凍結:

  1. Object.isFrozen(finalizedMarks); // returns true 

Object.seal 與 Object.freeze 略有不同。 Object.seal() 方法封閉一個對象,阻止添加新屬性并將所有現有屬性標記為不可配置。當前屬性的值只要可寫就可以改變。 

  1. var marks = {physics: 98, maths:95, chemistry: 91};  
  2. Object.seal(marks);  
  3. delete marks.chemistry; // returns false as operation failed  
  4. marks.physics = 95; // Works!  
  5. marks.greek = 86; // Will not add a new property  

同樣, 可以使用 Object.isSealed 判斷對象是否被密封。

  1. Object.isSealed(marks); // returns true 

在全局對象函數上還有許多其他重要的函數/方法,在這里找到他們。

6) 理解原型繼承

在傳統 JavaScript 中,有一種偽裝的繼承概念,它是通過使用原型技術來實現的。在ES5、ES6中看到使用 new 的語法只是底層原型OOP的語法糖。創建類是使用 JavaScript 中的函數完成的。

  1. var animalGroups = { 
  2.   MAMMAL: 1, 
  3.   REPTILE: 2, 
  4.   AMPHIBIAN: 3, 
  5.   INVERTEBRATE: 4 
  6. }; 
  7. function Animal(name, type) { 
  8.   this.name = name
  9.   this.type = type; 
  10. var dog = new Animal("dog", animalGroups.MAMMAL); 
  11. var crocodile = new Animal("crocodile", animalGroups.REPTILE);  

這里我們為類創建對象(使用 new 關鍵字),可以使用如下方式對類追加方法:

  1. Animal.prototype.shout = function() { 
  2.   console.log(this.name+'is'+this.sound+'ing...'); 
  3.  

這里你可能會有疑問。類中并沒 sound 屬性。是的,它打算由繼承了上述類的子類傳遞。

JavaScript中, 如下實現繼承: 

  1. function Dog(name, type) { 
  2. Animal.call(this, name, type);  
  3. this.sound = 'bow' 
  4.  

我定義了一個更具體的函數,叫做 Dog。在這里,為了繼承 Animal 類,我需要call傳遞this和其他參數。使用如下方式來實例化一只德國牧羊犬。

  1. var pet = Dog("德國牧羊犬", animalGroups.MAMMAL);  
  2. console.log(pet); // returns Dog {name"德國牧羊犬", type: 1, sound: "bow" 

我們沒有在子函數中分配 name 和 type 屬性,我們調用的是超級函數 Animal 并設置相應的屬性。pet 具有父類的屬性(name、type)。但是方法呢。他們也繼承的嗎? 來看看:

  1. pet.shout(); // Throws error 

為什么會這樣? 之所以發生這種情況,是因為沒有指定讓 JavaScript來繼承父類方法。 如何解決?

  1. // Link prototype chains 
  2. Dog.prototype = Object.create(Animal.prototype); 
  3. var pet = new Dog("germanShepard", animalGroups.MAMMAL); 
  4. // Now shout method is available 
  5. pet.shout(); // 德國牧羊犬 bowing...  

現在可以使用 shout 方法。 我們可以使用 object.constructor 函數檢查 JavaScript 中給定對象的類 來看看 pet 是什么類:

  1. pet.constructor; // returns Animal 

這是模糊的,Animal 是一個父類。但是 pet 到底是什么類型的呢? pet 應該是 Dog 的類型。之所以是 Animal 類型,是因為 Dog 類的構造函數:

  1. Dog.prototype.constructor; // returns Animal 

它是 Animal 類型的。我們應該將它設置為 Dog 本身,這樣類的所有實例(對象)才能給出正確的類名。

  1. Dog.prototype.constructor = Dog; 

關于原型繼承, 我們應該記住以下幾條:

  • 類屬性使用 this 綁定
  • 類方法使用 prototype 對象來綁定
  • 為了繼承屬性, 使用 call 函數來傳遞 this
  • 為了繼承方法, 使用 Object.create 連接父和子的原型
  • 始終將子類構造函數設置為自身,以獲得其對象的正確類型

7)理解 callback 和 promise

回調是在 I/O 操作完成后執行的函數。一個耗時的I/O操作會阻塞代碼, 因此在Python/Ruby不被允許。但是在 JavaScript中,由于允許異步執行,我們可以提供對異步函數的回調。這個例子是由瀏覽器到服務器的AJAX(XMLHettpRequest)調用,由鼠標、鍵盤事件生成。如下:

  1. function reqListener () { 
  2.   console.log(this.responseText); 
  3.  
  4. var req = new XMLHttpRequest(); 
  5. req.addEventListener("load", reqListener); 
  6. req.open("GET""http://www.example.org/example.txt"); 
  7. req.send();  

這里的 reqListener 是一個回調函數,當成功響應 GET 請求時將執行該回調函數。

Promise 是回調函數的優雅的封裝, 使得我們優雅的實現異步代碼。在以下給出的這篇文章中討論了很多 promise,這也是在 JS 中應該知道的重要部分。

8)理解正則表達

正則表達式有許多應用地方,處理文本、對用戶輸入執行規則等。JavaScript 開發人員應該知道如何執行基本正則表達式并解決問題。Regex 是一個通用概念,來看看如何從 JS 中做到這一點。

創建正則表達式,有如下兩種方式:

  1. var re = /ar/;  
  2. var re = new RegExp('ar');  

上面的正則表達式是與給定字符串集匹配的表達式。定義正則表達式之后,我們可以嘗試匹配并查看匹配的字符串。可以使用 exec 函數匹配字符串:

  1. re.exec("car"); // returns ["ar"index: 1, input: "car" 
  2. re.exec("cab"); // returns null  

有一些特殊的字符類允許我們編寫復雜的正則表達式。RegEx 中有許多類型的元素,其中一些如下:

  • 字符正則:\w-字母數字, \d- 數字, \D- 沒有數字
  • 字符類正則:[x-y] x-y區間, [^x] 沒有x
  • 數量正則:+ 至少一個、? 沒或多個、* 多個
  • 邊界正則,^ 開始、$ 結尾

例子如下:

  1. /* Character class */ 
  2.  
  3. var re1 = /[AEIOU]/; 
  4. re1.exec("Oval"); // returns ["O"index: 0, input: "Oval"
  5. re1.exec("2456"); // null 
  6. var re2 = /[1-9]/; 
  7. re2.exec('mp4'); // returns ["4"index: 2, input: "mp4"
  8.  
  9. /* Characters */ 
  10.  
  11. var re4 = /\d\D\w/; 
  12. re4.exec('1232W2sdf'); // returns ["2W2"index: 3, input: "1232W2sdf"
  13. re4.exec('W3q'); // returns null 
  14.  
  15. /* Boundaries */ 
  16.  
  17. var re5 = /^\d\D\w/; 
  18. re5.exec('2W34'); // returns ["2W3"index: 0, input: "2W34"
  19. re5.exec('W34567'); // returns null 
  20. var re6 = /^[0-9]{5}-[0-9]{5}-[0-9]{5}$/; 
  21. re6.exec('23451-45242-99078'); // returns ["23451-45242-99078"index: 0, input: "23451-45242-99078"
  22. re6.exec('23451-abcd-efgh-ijkl'); // returns null 
  23.  
  24. /* Quantifiers */ 
  25.  
  26. var re7 = /\d+\D+$/; 
  27. re7.exec('2abcd'); // returns ["2abcd"index: 0, input: "2abcd"
  28. re7.exec('23'); // returns null 
  29. re7.exec('2abcd3'); // returns null 
  30. var re8 = /<([\w]+).*>(.*?)<\/\1>/; 
  31. re8.exec('<p>Hello JS developer</p>'); //returns  ["<p>Hello JS developer</p>""p""Hello JS developer"index: 0, input: "<p>Hello JS developer</p>" 

除了 exec 之外,還有其他函數,即 match、search 和 replace,可以使用正則表達式在另一個字符串中查找字符串,但是這些函數在字符串本身上使用。

  1. "2345-678r9".match(/[a-z A-Z]/); // returns ["r"index: 8, input: "2345-678r9" 
  2. "2345-678r9".replace(/[a-z A-Z]/, ""); // returns 2345-6789  

Regex 是一個重要的主題,開發人員應該理解它,以便輕松解決復雜的問題。

9)理解 map、reduce 和 filter

函數式編程是當今的一個熱門討論話題。許多編程語言都在新版本中包含了函數概念,比如 lambdas(例如:Java >7)。在 JavaScrip t中,函數式編程結構的支持已經存在很長時間了。我們需要深入學習三個主要函數。數學函數接受一些輸入和返回輸出。純函數都是給定的輸入返回相同的輸出。我們現在討論的函數也滿足純度。

map

map 函數在 JavaScript 數組中可用,使用這個函數,我們可以通過對數組中的每個元素應用一個轉換函數來獲得一個新的數組。map 一般語法是:

  1. arr.map((elem){ 
  2.     process(elem) 
  3.     return processedValue 
  4. }) // returns new array with each element processed  

假設,在我們最近使用的串行密鑰中輸入了一些不需要的字符,需要移除它們。此時可以使用 map 來執行相同的操作并獲取結果數組,而不是通過迭代和查找來刪除字符。

  1. var data = ["2345-34r""2e345-211""543-67i4""346-598"];  
  2. var re = /[a-z A-Z]/;  
  3. var cleanedData = data.map((elem) => {return elem.replace(re, "")});  
  4. console.log(cleanedData); // ["2345-34""2345-211""543-674""346-598" 

map 接受一個作為參數的函數, 此函數接受一個來自數組的參數。我們需要返回一個處理過的元素, 并應用于數組中的所有元素。

reduce

reduce 函數將一個給定的列表整理成一個最終的結果。通過迭代數組執行相同的操作, 并保存中間結果到一個變量中。這里是一個更簡潔的方式進行處理。js 的 reduce 一般使用語法如下:

  1. arr.reduce((accumulator, 
  2.            currentValue, 
  3.            currentIndex) => { 
  4.            process(accumulator, currentValue) 
  5.            return intermediateValue/finalValue 
  6. }, initialAccumulatorValue) // returns reduced value  

accumulator 存儲中間值和最終值。currentIndex、currentValue分別是數組中元素的 index 和 value。initialAccumulatorValue 是 accumulator 初始值。

reduce 的一個實際應用是將一個數組扁平化, 將內部數組轉化為單個數組, 如下: 

  1. var arr = [[1, 2], [3, 4], [5, 6]];  
  2. var flattenedArray = [1, 2, 3, 4, 5, 6];  

我們可以通過正常的迭代來實現這一點,但是使用 reduce,代碼會更加簡潔。

  1. var flattenedArray = arr.reduce((accumulator, currentValue) => { 
  2.     return accumulator.concat(currentValue); 
  3. }, []); // returns [1, 2, 3, 4, 5, 6]  

filter

filter 與 map 更為接近, 對數組的每個元素進行操作并返回另外一個數組(不同于 reduce 返回的值)。過濾后的數組可能比原數組長度更短,因為通過過濾條件,排除了一些我們不需要的。

filter 語法如下: 

  1. arr.filter((elem) => {  
  2. return true/false  
  3. })  

elem 是數組中的元素, 通過 true/false 表示過濾元素保存/排除。假設, 我們過濾出以 t 開始以 r 結束的元素:

  1. var words = ["tiger""toast""boat""tumor""track""bridge"
  2. var newData = words.filter((str) => { 
  3.     return str.startsWith('t') && str.endsWith('r'); 
  4. }) 
  5. newData // (2) ["tiger""tumor" 

當有人問起JavaScript的函數編程方面時,這三個函數應該信手拈來。 如你所見,原始數組在所有三種情況下都沒有改變,這證明了這些函數的純度。

10) 理解錯誤處理模式

這是許多開發人員最不關心的 JavaScript。 我看到很少有開發人員談論錯誤處理, 一個好的開發方法總是謹慎地將 JS 代碼封裝裝在 try/catch 塊周圍。

在 JavaScript中,只要我們隨意編寫代碼,就可能會失敗,如果所示:

  1. $("button").click(function(){ 
  2.     $.ajax({url: "user.json", success: function(result){ 
  3.         updateUI(result["posts"]); 
  4.     }}); 
  5. });  

這里,我們陷入了一個陷阱,我們說 result 總是 JSON 對象。但有時服務器會崩潰,返回的是 null 而不是 result。在這種情況下,null["posts"] 將拋出一個錯誤。正確的處理方式可能是這樣的:

  1. $("button").click(function(){ 
  2.     $.ajax({url: "user.json", success: function(result){ 
  3.      
  4.       try {      
  5.         updateUI(result["posts"]); 
  6.        } 
  7.       catch(e) { 
  8.         // Custom functions 
  9.         logError(); 
  10.         flashInfoMessage();       
  11.       } 
  12.     }}); 
  13. });  

logError 函數用于向服務器報告錯誤。flashInfoMessage 是顯示用戶友好的消息,如“當前不可用的服務”等。

Nicholas 說,當你覺得有什么意想不到的事情將要發生時,手動拋出錯誤。區分致命錯誤和非致命錯誤。以上錯誤與后端服務器宕機有關,這是致命的。在那里,應該通知客戶由于某種原因服務中斷了。

在某些情況下,這可能不是致命的,但***通知服務器。為了創建這樣的代碼,首先拋出一個錯誤,, 從 window 層級捕捉錯誤事件,然后調用API將該消息記錄到服務器。

  1. reportErrorToServer = function (error) { 
  2.   $.ajax({type: "POST",  
  3.           url: "http://api.xyz.com/report"
  4.           data: error, 
  5.           success: function (result) {} 
  6.   }); 
  7. // Window error event 
  8. window.addEventListener('error'function (e) { 
  9.   reportErrorToServer({message: e.message}) 
  10. })} 
  11. function mainLogic() { 
  12.   // Somewhere you feel like fishy 
  13.   throw new Error("user feeds are having fewer fields than expected..."); 
  14.  

這段代碼主要做三件事:

  • 監聽window層級錯誤
  • 無論何時發生錯誤,都要調用 API
  • 在服務器中記錄

你也可以使用新的 Boolean 函數(es5,es6)在程序之前監測變量的有效性并且不為null、undefined。

  1. if (Boolean(someVariable)) { 
  2. // use variable now 
  3. else { 
  4.     throw new Error("Custom message"
  5.  

始終考慮錯誤處理是你自己, 而不是瀏覽器。

其他(提升機制和事件冒泡)

以上所有概念都是 JavaScript 開發人員的需要知道基本概念。有一些內部細節需要知道,這些對你會有很在幫助。 這些是JavaScript引擎在瀏覽器中的工作方式,什么是提升機制和事件冒泡?

提升機制

變量提升是 在代碼執行過程中將聲明的變量的作用域提升到全局作用哉中的一個過程,如: 

  1. doSomething(foo); // used before  
  2. var foo; // declared later  

當在 Python 這樣的腳本語言中執行上述操作時,它會拋出一個錯誤,因為需要先定義然后才能使用它。盡管 JS 是一種腳本語言,但它有一種提升機制,在這種機制中,JavaScript VM 在運行程序時做兩件事:

  1. 首先掃描程序,收集所有的變量和函數聲明,并為其分配內存空間
  2. 通過填充分配的變量來執行程序, 沒有分配則填充 undefined

在上面的代碼片段中,console.log 打印 “undefined”。 這是因為在***次傳遞變量 foo 被收集。 JS 虛擬機 查找為變量 foo 定義的任何值。 這種提升可能導致許多JavaScript 在某些地方拋出錯誤,和另外地方使用 undefined 。

學習一些 例子來搞清楚提升。

事件冒泡

現在事件開始冒泡了! 根據高級軟件工程師 Arun P的說法:

“當事件發生在另一個元素內的元素中時,事件冒泡和捕獲是 HTML DOM API 中事件傳播的兩種方式,并且這兩個元素都已為該事件注冊了處理程序,事件傳播模式確定元素接收事件的順序。“

通過冒泡,事件首先由最內部的元素捕獲和處理,然后傳播到外部元素。對于捕獲,過程是相反的。我們通常使用addEventListener 函數將事件附加到處理程序。

  1. addEventListener("click", handler, useCapture=false

useCapture 是第三個參數的關鍵詞, 默認為 false。因此, 冒泡模式是事件由底部向上傳遞。 反之, 這是捕獲模式。

冒泡模式:

  1. <div onClick="divHandler()"
  2.     <ul onClick="ulHandler"
  3.         <li id="foo"></li> 
  4.     </ul> 
  5. </div> 
  6. <script> 
  7. function handler() { 
  8.  // do something here 
  9. function divHandler(){} 
  10. function ulHandler(){} 
  11. document.getElementById("foo").addEventListener("click", handler) 
  12. </script>  

點擊li元素, 事件順序:

handler() => ulHandler() => divHandler()   

 

在圖中,處理程序按順序向外觸發。類似地,捕獲模型試圖將事件從父元素向內觸發到單擊的元素。現在更改上面代碼中的這一行。

  1. document.getElementById("foo").addEventListener("click", handler, true

事件順序:

divHandler => ulHandler() => handler()  

 

你應該正確地理解事件冒泡(無論方向是指向父節點還是子節點),以實現用戶界面(UI),以避免任何不需要的行為。

這些是 JavaScrip t中的基本概念。正如我最初提到的,除了工作經驗和知識之外,準備有助理于你通過 JavaScript 面試。始終保持學習。留意***的發展(第六章)。深入了解JavaScript的各個方面,如 V6 引擎、測試等。***,沒有掌握數據結構和算法的面試是不成功的。Oleksii Trekhleb 策劃了一個很棒的 git repo,它包含了所有使用 JS 代碼的面試準備算法。 

代碼部署后可能存在的BUG沒法實時知道,事后為了解決這些BUG,花了大量的時間進行log 調試,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。

 

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2022-01-21 21:33:03

開發JavaScript應用

2021-08-01 22:59:16

Python工具開發

2022-05-31 17:36:25

技術面試編程

2024-02-01 09:37:42

Kubernetes服務網格? 命令

2024-05-07 08:45:16

OpenAILlamaIndex大語言模型

2018-03-27 23:25:40

Paddle

2019-07-04 09:00:00

Web控制器架構

2015-09-01 15:51:16

TalkingData

2019-08-16 10:55:37

開發者技能AI

2017-03-24 09:37:45

前端開發者JavaScript面試題

2017-11-27 13:09:00

AndroidGradle代碼

2022-01-02 23:26:08

開發SDK Sentry

2022-01-15 23:33:47

SentryPyCharm配置

2022-01-18 23:26:45

開發

2009-02-19 08:46:31

Windows 7開發者指南下載

2011-04-13 11:31:06

PIM APIBlackBerry

2011-07-19 09:51:32

性能優化Designing FAndroid

2022-01-11 20:42:54

開發Sentry標志

2011-04-13 09:55:16

Mail APIBlackBerry

2011-04-13 13:38:57

選項APIBlackBerry
點贊
收藏

51CTO技術棧公眾號

美女又爽又黄视频毛茸茸| 日韩国产精品一区二区| 欧美黄色免费在线观看| 欧美成人基地| 在线免费不卡电影| 日本国产中文字幕| 久久这里精品| 精品一区在线看| 久久久久久久久久久国产| 中文字幕免费高清| 警花av一区二区三区| 色综合天天性综合| 肉大捧一出免费观看网站在线播放 | 亚洲激情77| 在线电影国产精品| 日本精品免费在线观看| 黄色网在线播放| 91在线免费视频观看| 成人在线播放av| 亚洲天堂视频网站| 欧美日韩hd| 这里精品视频免费| 亚洲精品乱码久久| 高清一区二区三区av| 日本高清视频一区二区| 成年人网站国产| 黄色网页在线免费观看| 国产午夜亚洲精品理论片色戒| 亚洲一区二区免费在线| 中文在线最新版天堂| 亚洲小说欧美另类社区| www亚洲精品| 日韩一区二区a片免费观看| av不卡一区二区| 欧美性一二三区| 精品中文字幕av| 爱搞国产精品| 亚洲图片欧美色图| 天天综合五月天| av在线电影院| 国产日韩欧美精品一区| 欧美激情专区| 天堂网在线播放| 高清av一区二区| 97久久精品午夜一区二区| 中文字幕乱码中文字幕| 日韩精品一卡二卡三卡四卡无卡| 欧美精品一二区| 国产av 一区二区三区| 99久久九九| xvideos成人免费中文版| 亚洲欧美va天堂人熟伦 | 夜夜春亚洲嫩草影视日日摸夜夜添夜 | 波多野结衣久久精品| 午夜精品久久久久久久99樱桃 | 暖暖在线中文免费日本| 一区二区三区在线播| 日韩中文在线字幕| av网址在线| 一区二区在线观看免费视频播放| 看一级黄色录像| 新版中文在线官网| 一区二区三区四区激情| 亚洲 欧美 综合 另类 中字| 国产精品剧情一区二区在线观看| 亚洲天堂久久久久久久| 永久免费网站视频在线观看| 国产激情在线| 亚洲国产精品麻豆| 中文字幕无码精品亚洲35| 国产污视频在线播放| 色先锋aa成人| 乌克兰美女av| 欧美日本三级| 亚洲国产成人精品女人久久久| 黄色污在线观看| 久久av导航| 久久精品国产综合| 久久久久99精品成人片毛片| 一本色道久久综合一区| 国产www精品| 国产精品久久久久久免费| 国产精品1024| 久久波多野结衣| av在线播放网| 亚洲影院在线观看| 成年人网站国产| 欧美大片1688网站| 日韩片之四级片| 欧美成人三级伦在线观看| 国产探花一区二区| 欧美剧在线观看| 亚洲 欧美 中文字幕| 激情综合亚洲精品| 精品乱码一区| 日本在线观看| 精品国产1区2区| 免费网站在线观看黄| 麻豆精品少妇| 少妇高潮久久77777| 国产精品成人av久久| 蜜桃视频在线观看一区二区| 国产91免费视频| 国产免费av高清在线| 一区二区三区不卡在线观看| 男人插女人下面免费视频| 日韩一二三区| 中文国产成人精品久久一| 久久一二三四区| 美女高潮久久久| 好看的日韩精品视频在线| 欧洲日本在线| 日韩欧美aⅴ综合网站发布| 日本黄色www| 精品国产成人| 69av在线播放| 午夜精品久久久久久久第一页按摩| 久久婷婷国产综合精品青草| 成人手机在线播放| 亚洲精品伊人| 在线播放国产一区中文字幕剧情欧美| 久久午夜鲁丝片午夜精品| 久久精品国产99久久6| 久久久久久久久一区| 污污网站在线看| 欧美电影在线免费观看| 中国美女乱淫免费看视频| 亚洲国产mv| 99久久久久国产精品免费| 免费看美女视频在线网站 | 97国产精品久久久| 久久精品一区二区三区不卡牛牛| 无码专区aaaaaa免费视频| 欧美影院视频| 欧美片一区二区三区| 国产精品久久久久久久久久久久久久久久 | 日韩电影在线免费看| 免费在线成人av电影| 欧美gv在线观看| 亚洲经典中文字幕| 久久精品人妻一区二区三区| 国产精品1区2区3区| 久久视频免费在线| 日本久久伊人| 欧美另类在线观看| 国内老熟妇对白hdxxxx| 亚洲日本一区二区三区| 国产成人美女视频| 68国产成人综合久久精品| 成人福利在线视频| 国产人成网在线播放va免费| 91麻豆精品国产| 国产亚洲精品久久久久久豆腐| 日本成人在线电影网| 亚洲精品高清视频| 精品九九久久| 久久综合免费视频影院| av小说天堂网| 亚洲一区二区三区视频在线 | 国产伦一区二区| 亚洲男同性视频| 丰满人妻一区二区三区免费视频棣| 狠狠爱综合网| 久久riav| 欧美另类激情| 欧美另类高清videos| 色婷婷av一区二区三| 色香蕉成人二区免费| 人妻互换一区二区激情偷拍| 国内精品国产三级国产a久久| 中文字幕色呦呦| 欧美电影在线观看免费| 国产精品69av| 黄色免费在线看| 精品久久国产97色综合| 欧美a视频在线观看| 国产精品丝袜一区| 无人码人妻一区二区三区免费| 欧美视频成人| 欧洲亚洲一区二区三区四区五区| 国产成人精选| 欧美丰满少妇xxxxx| 欧洲亚洲在线| 欧美放荡的少妇| 天海翼一区二区| 中文成人综合网| 无码人妻丰满熟妇啪啪网站| 可以看av的网站久久看| 翔田千里亚洲一二三区| 77成人影视| 国产精品扒开腿爽爽爽视频| 性欧美videoshd高清| 国产一区二区三区在线视频| aaaa一级片| 色妞www精品视频| 免费视频网站www| 国产日韩欧美在线一区| 性活交片大全免费看| 蜜桃免费网站一区二区三区| 日本在线xxx| 国产大片一区| 免费亚洲一区二区| 日韩成人视屏| 国产精品免费视频久久久| caoprom在线| www.日韩.com| 国产一级在线| 亚洲高清色综合| 国产精品-色哟哟| 日韩欧美中文在线| 久久国产一级片| 中文字幕日韩一区| 瑟瑟视频在线观看| 成人黄色在线看| 在线观看中文av| 青青草成人在线观看| 男人日女人下面视频| 欧美激情视频一区二区三区在线播放 | 亚洲小说区图片区| 中文字幕一区二区三区乱码| 国产成人精品一区二区免费看京 | 国产精品午夜视频| 三级中文字幕在线观看| 欧美精品激情在线| 成人在线影视| 久久精品视频导航| 国产精品久久久久一区二区国产 | 欧美日韩国产乱码电影| 国产精品乱子伦| 亚洲图片欧美视频| 久久亚洲av午夜福利精品一区| 亚洲欧洲国产日本综合| 成人小视频免费看| 久久久久久免费毛片精品| 好男人香蕉影院| 不卡高清视频专区| aaa黄色大片| 国产成人av电影在线观看| 久久精品亚洲天堂| 国内久久婷婷综合| 中文字幕免费高清在线| 久久99久久99精品免视看婷婷| 搡女人真爽免费午夜网站| 日本三级亚洲精品| 天堂av在线网站| 日韩电影免费在线| 午夜在线观看av| 免费观看在线色综合| 一级黄色特级片| 精品一区二区三区在线播放 | 九九久久综合网站| 性xxxfreexxxx性欧美| 久久久久久中文| av2020不卡| 久久久久久网址| 亚洲欧洲高清| 国产精品久久久久9999| 久久久国产精品网站| 成人激情在线播放| 亚洲91网站| 精品在线视频一区二区| 亚洲人成精品久久久| 偷拍视频一区二区| 91精品啪在线观看国产18| 久久天天东北熟女毛茸茸| 欧美视频四区| 中国丰满人妻videoshd | 成年人在线观看网站| 最近2019年中文视频免费在线观看 | 久久久精品免费| 国产白丝在线观看| 国产69久久精品成人看| 深夜视频一区二区| 91视频免费网站| 福利在线一区| 日韩精品在在线一区二区中文| 久久一区二区三区喷水| 日韩免费在线观看av| 校园春色综合网| 男人的天堂最新网址| 成人黄色a**站在线观看| 国产毛片久久久久久久| 亚洲天堂成人在线观看| 国产一级在线观看视频| 在线免费观看一区| 国产成人精品a视频| 日韩精品极品在线观看| 免费a级毛片在线播放| 国内自拍欧美激情| 99亚洲伊人久久精品影院| 懂色一区二区三区av片| 精品国产一区二区三区香蕉沈先生| 日本黄xxxxxxxxx100| 羞羞视频在线观看欧美| 中文字幕一区二区在线观看视频| 99久久婷婷国产| 久久精品一区二区三区四区五区| 亚洲v日本v欧美v久久精品| 国产精华7777777| 亚洲成人网在线观看| 在线国产91| 欧美一级片免费在线| 免费欧美网站| 日韩欧美三级一区二区| 伊人久久成人| 婷婷激情综合五月天| 久久精品一区二区三区不卡牛牛| 国产精品999久久久| 欧美精选午夜久久久乱码6080| 天堂а√在线8种子蜜桃视频 | 激情视频网站在线播放色| 91麻豆桃色免费看| 精品99在线| 午夜精品久久久久久久无码| 国产成人综合在线观看| 欧美美女性生活视频| 色久优优欧美色久优优| 污污网站免费在线观看| 久久91亚洲精品中文字幕奶水| 日本精品网站| 欧美色图亚洲自拍| 在线日韩中文| 欧美午夜精品一区二区| 亚洲猫色日本管| 一区不卡在线观看| 一夜七次郎国产精品亚洲| 中老年在线免费视频| 国产乱码精品一区二区三区日韩精品| 国产精品99一区二区三区| 天天色综合社区| 欧美国产精品中文字幕| 日本a级c片免费看三区| 精品视频—区二区三区免费| 爱啪视频在线观看视频免费| 国产精品推荐精品| 国产精品啊v在线| 制服.丝袜.亚洲.中文.综合懂| 亚洲乱码中文字幕综合| 国产丰满美女做爰| 欧美另类在线播放| 9l亚洲国产成人精品一区二三 | 成人影音在线| 国产伦精品一区二区三区视频孕妇| 午夜精品久久99蜜桃的功能介绍| 在线观看一区二区三区视频| 一区二区三区在线视频播放 | 精品国产亚洲一区二区三区大结局| 在线观看欧美激情| 国产综合久久久久影院| 国产97免费视频| 精品少妇一区二区三区日产乱码 | 91精品免费视频| 中文字幕日韩一区二区不卡 | 国产精品护士白丝一区av| 在线观看国产成人| 久久亚洲综合国产精品99麻豆精品福利| 国产精品日本一区二区不卡视频| 四虎精品欧美一区二区免费| 国产91色综合久久免费分享| 亚洲精品77777| 亚洲欧美一区二区精品久久久| 另类中文字幕国产精品| 正在播放亚洲| 成人免费黄色在线| 亚洲永久精品在线观看| 中日韩美女免费视频网站在线观看| 大胆国模一区二区三区| 六月婷婷激情综合| 久久在线观看免费| 中文字幕精品一区二| 欧美精品一本久久男人的天堂| 国产毛片精品| 国产天堂在线播放| 亚洲欧美电影院| 五月色婷婷综合| 国产一区欧美二区三区| 欧美精品一线| 泷泽萝拉在线播放| 欧美久久一二区| 91高清视频在线观看| 日韩av影视| 丁香婷婷深情五月亚洲| 天干夜夜爽爽日日日日| 另类天堂视频在线观看| 欧美美女在线直播| 亚洲欧美自偷自拍另类| 亚洲午夜久久久久| 国产区视频在线| 国产精品亚洲不卡a| 蜜桃视频免费观看一区| 日本学生初尝黑人巨免费视频| 在线视频免费一区二区| 日本少妇精品亚洲第一区| 成人一级片网站| 亚洲柠檬福利资源导航| 大乳在线免费观看| 国产精品一区在线观看| 韩国成人精品a∨在线观看| 国产午夜免费福利| 欧美大奶子在线|