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

JavaScript 中 10 個需要掌握基礎的問題

開發 前端
JavaScript 是一種客戶端編程語言。全球超過**90%**的網站都在使用它,它是世界上最常用的編程語言之一。因此,今天我們業討論 10 個有關 JavaScript 的常見問題。

[[344637]]

JavaScript 是一種客戶端編程語言。全球超過**90%**的網站都在使用它,它是世界上最常用的編程語言之一。因此,今天我們業討論 10 個有關 JavaScript 的常見問題。

1.如何從數組中移除一個特定的項

思路:首先,使用indexOf查找要刪除的數組元素的索引(index),然后使用splice方法刪除該索引所對應的項。

splice()是一個非純函數,通過刪除現有元素和/或添加新元素來更改數組的內容。

  1. const array = [2, 5, 9] 
  2.  
  3. const index = array.indexOf(5) 
  4. if (index > -1) { 
  5.   array.splice(index, 1) 
  6.  
  7. console.log(array) 
  8. // [ 2, 9 ] 

splice的第二個參數是要刪除的元素數量。注意,splice會在適當的位置修改數組,并返回一個包含已刪除元素的新數組。

接著,我們可以來完善一下。下面有兩個函數,第一個函數僅刪除一個匹配項(即從[2,5,9,1,5,8,5]中刪除第一個匹配項5),而第二個函數則刪除所有匹配項:

  1. // 僅刪除第一個匹配項 
  2. function removeItemOnce (arr, value) { 
  3.   let index = arr.indexOf(value) 
  4.   if (index > -1) { 
  5.     arr.splice(index, 1) 
  6.   } 
  7.   return arr 
  8.  
  9. // 刪除所有匹配項 
  10. function removeItemAll (arr, value) { 
  11.   let i = 0 
  12.   while(i < arr.length) { 
  13.     if (arr[i] === value) { 
  14.       arr.splice(i, 1) 
  15.     } else { 
  16.       ++i 
  17.     } 
  18.   } 

刪除數組中索引i處的元素:

刪除數組中索引i處的元素:

  1. array.splice(i, 1) 

如果你想從數組中刪除值為number的每個元素,可以這樣做:

  1. for (let i = array.length - 1; i>=0; i--) { 
  2.   if (array[i] === number) { 
  3.     array.splice(i, 1) 
  4.   } 
  5. 如果你只想使索 

如果你只想使索引i處的元素不再存在,但又不想更改其他元素的索引:

  1. delete array[i] 

2. 如何使用 jQuery 或純 JS 將用戶從一個頁面重定向到另一個頁面

jQuery 不是必需的,window.location.replace(…)最適合模擬 HTTP 重定向。window.location.replace(...)優于使用window.location.href,因為replace()不會將原始頁面保留在會話歷史記錄中,這意味著用戶將不會陷入永無休止回退按鈕。

如果要模擬單擊鏈接,可以使用location.href,如果要模擬HTTP重定向,請使用location.replace。

事例:

  1. //模擬HTTP重定向 
  2. window.location.replace("http://stackoverflow.com"
  3.  
  4. // 模擬單擊鏈接 
  5. window.location.href = "http://stackoverflow.com" 

你還可以這樣做:

  1. $(location).attr('href''http://stackoverflow.com'

3.JavaScript 閉包是如何工作的

閉包是一個函數和對該函數外部作用域的引用(詞法環境),詞法環境是每個執行上下文(堆棧)的一部分,并且是標識符(即局部變量名稱)和值之間的映射。

JavaScript 中的每個函數都維護對其外部詞法環境的引用。此引用用于配置調用函數時創建的執行上下文。不管何時調用函數,該引用使函數內的代碼能夠查看在函數外聲明的變量。

在下面的代碼中,inner與調用foo時創建的執行上下文的詞法環境一起形成一個閉包,并對外部隱藏了變量secret:

  1. function foo() { 
  2.   const secret = Math.trunc(Math.random()*100) 
  3.   return function inner() { 
  4.     console.log(`The secret number is ${secret}.`) 
  5.   } 
  6. const f = foo() // secret 不能從foo 外部直接訪問 
  7. f() // 訪問 secret 的唯一辦法就是調用 f 

換句話說,在JavaScript中,函數帶有對私有狀態的引用,只有它們(以及在相同的詞法環境中聲明的任何其他函數)可以訪問該私有狀態。這個狀態對函數的調用者是不可見的,這為數據隱藏和封裝提供了一種優秀的機制。

請記住,JavaScript中的函數可以像變量一樣傳遞,這意味著這些功能和狀態的對可以在程序中傳遞:類似于在c++中傳遞類的實例。

如果JavaScript沒有閉包,則必須在函數之間顯式傳遞更多狀態,從而使參數列表更長,代碼更冗余。

所以,如果你想讓一個函數總是能夠訪問私有狀態,你可以使用一個閉包,我們經常想把狀態和函數聯系起來。例如,在Java或c++中,當你向類添加私有實例變量和方法時,這是將狀態與功能關聯起來。

在 C 語言和大多數其他編程語言中,函數返回后,由于堆棧被銷毀,所有的局部變量都不再可訪問。在JavaScript中,如果在另一個函數中聲明一個函數,那么外部函數的本地變量在返回后仍然可以訪問。這樣,在上面的代碼中,secret在從foo返回后仍然對函數對象內部可用。

閉包在需要與函數關聯的私有狀態時非常有用。這是一個非常常見的場景,JavaScript直到2015年才有類語法,它仍然沒有私有字段語法,閉包滿足了這一需求。

私有實例變量

在下面的事例中,函數 toString 隱藏了 Car 類的一些細節。

  1. function Car(manufacturer, model, year, color) { 
  2.   return { 
  3.     toString() { 
  4.       return `${manufacturer} ${model} (${year}, ${color})` 
  5.     } 
  6.   } 
  7. const car = new Car('Aston Martin','V8 Vantage','2012','Quantum Silver'
  8. console.log(car.toString()) 

函數式編程

在下面的代碼中,函數inner隱藏了fn和args。

  1. function curry(fn) { 
  2.   const args = [] 
  3.   return function inner(arg) { 
  4.     if(args.length === fn.length) return fn(...args) 
  5.     args.push(arg) 
  6.     return inner 
  7.   } 
  8.  
  9. function add(a, b) { 
  10.   return a + b 
  11.  
  12. const curriedAdd = curry(add
  13. console.log(curriedAdd(2)(3)()) // 5 

面向事件的編程

在以下代碼中,函數onClick隱藏了變量BACKGROUND_COLOR。

  1. const $ = document.querySelector.bind(document) 
  2. const BACKGROUND_COLOR = 'rgba(200,200,242,1)' 
  3.  
  4. function onClick() { 
  5.   $('body').style.background = BACKGROUND_COLOR 
  6.  
  7. $('button').addEventListener('click', onClick) 
  8. <button>Set background color</button> 

模塊化

在下面的示例中,所有實現細節都隱藏在一個立即執行的函數表達式中。函數tick和toString隱藏了私有狀態和函數,它們需要完成自己的工作。閉包使我們能夠模塊化和封裝我們的代碼。

  1. let namespace = {}; 
  2.  
  3. (function foo(n) { 
  4.   let numbers = [] 
  5.   function format(n) { 
  6.     return Math.trunc(n) 
  7.   } 
  8.   function tick() { 
  9.     numbers.push(Math.random() * 100) 
  10.   } 
  11.   function toString() { 
  12.     return numbers.map(format) 
  13.   } 
  14.   n.counter = { 
  15.     tick, 
  16.     toString 
  17.   } 
  18. }(namespace)) 
  19.  
  20. const counter = namespace.counter 
  21. counter.tick() 
  22. counter.tick() 
  23. console.log(counter.toString()) 

事例 1:

此示例演示局部變量未在閉包中復制。閉包保留對原始變量本身的引用。似乎即使外部函數退出后,堆棧仍在內存中保留。

  1. function foo () { 
  2.   let x = 42 
  3.   let inner = function () { 
  4.     console.log(x) 
  5.   } 
  6.   x = x + 1 
  7.   return inner 
  8.  
  9. let f = foo() 
  10. f() 

事例 2:

在下面的代碼中,三種方法log ,increment 和update 都在同一詞法環境閉包中。

  1. function createObject() { 
  2.   let x = 42; 
  3.   return { 
  4.     log() { console.log(x) }, 
  5.     increment() { x++ }, 
  6.     update(value) { x = value } 
  7.   } 
  8.  
  9. const o = createObject() 
  10. o.increment() 
  11. o.log() // 43 
  12. o.update(5) 
  13. o.log() // 5 
  14. const p = createObject() 
  15. p.log() // 42 

事例 3:

如果使用的變量是使用var聲明的,需要注意的一點是,使用var聲明的變量被提升。由于引入了let和const,這在現代JavaScript 中幾乎沒有問題。

在下面的代碼中,每次循環中,都會創建一個新的inner函數,變量i被覆蓋,但是因var會讓 i 提升到函數的頂部,所以所有這些inner函數覆蓋的都是同一個變量,這意味著i(3)的最終值被打印了三次。

  1. function foo () { 
  2.   var result = [] 
  3.   for (var i = 0; i < 3; i++) { 
  4.     result.push(function inner () { 
  5.       console.log(i) 
  6.     }) 
  7.   } 
  8.   return result 
  9. const result = foo() 
  10.  
  11. for(var i = 0; i < 3; i++) { 
  12.   result[i]() 
  13. // 3 3 3 

最后一點:

  • 每當在JavaScript中聲明函數時,都會創建一個閉包。
  • 從一個函數內部返回另一個函數是閉包的經典例子,因為外部函數內部的狀態對于返回的內部函數是隱式可用的,即使外部函數已經完成執行。
  • 只要在函數內使用eval(),就會使用一個閉包。eval的文本可以引用函數的局部變量,在非嚴格模式下,甚至可以通過使用eval('var foo = ')創建新的局部變量。
  • 當在函數內部使用new Function()(Function constructor)時,它不會覆蓋其詞法環境,而是覆蓋全局上下文。新函數不能引用外部函數的局部變量。
  • 在JavaScript中,閉包類似于在函數聲明時保留對作用域的引用(而不是復制),后者又保留對其外部作用域的引用,以此類推,一直到作用域鏈頂端的全局對象。
  • 聲明函數時創建一個閉包。當調用函數時,此閉包用于配置執行上下文。
  • 每次調用函數時都會創建一組新的局部變量。

JavaScript 中的每個函數都維護與其外部詞法環境的鏈接。詞法環境是所有名稱的映射(例如,變量,參數)及其范圍內的值。因此,只要看到function關鍵字,函數內部的代碼就可以訪問在函數外部聲明的變量。

  1. function foo(x) { 
  2.   var tmp = 3; 
  3.  
  4.   function bar(y) { 
  5.     console.log(x + y + (++tmp)); // 16 
  6.   } 
  7.  
  8.   bar(10); 
  9.  
  10. foo(2); 

上面輸出結果是16,參數x和變量tmp都存在于外部函數foo的詞法環境中。函數bar及其與函數foo的詞法環境的鏈接是一個閉包。

函數不必返回即可創建閉包。僅僅憑借其聲明,每個函數都會在其封閉的詞法環境中關閉,從而形成一個閉包。

  1. function foo(x) { 
  2.   var tmp = 3; 
  3.  
  4.   return function (y) { 
  5.     console.log(x + y + (++tmp)); // 16 
  6.   } 
  7.  
  8. var bar = foo(2); 
  9. bar(10); // 16 
  10. bar(10); // 17 

上面還是打印16,因為bar內的代碼仍然可以引用參數x和變量tmp,即使它們不再直接的作用域內。

但是,由于tmp仍然在bar的閉包內部徘徊,因此可以對其進行遞增。每次調用bar時,它將增加1。

閉包最簡單的例子是這樣的:

  1. var a = 10; 
  2.  
  3. function test() { 
  4.   console.log(a); // will output 10 
  5.   console.log(b); // will output 6 
  6. var b = 6; 
  7. test(); 

當調用一個JavaScript函數時,將創建一個新的執行上下文ec。連同函數參數和目標對象,這個執行上下文還接收到調用執行上下文的詞法環境的鏈接,這意味著在外部詞法環境中聲明的變量(在上面的例子中,a和b)都可以從ec獲得。

每個函數都會創建一個閉包,因為每個函數都有與其外部詞法環境的鏈接。

注意,變量本身在閉包中是可見的,而不是副本。

4. use strict 在 JavaScript 中做了什么,背后的原因是什么

引用一些有趣的部分:

嚴格模式是ECMAScript 5中的一個新特性,它允許我們將程序或函數放置在嚴格的操作上下文中。這種嚴格的上下文會防止某些操作被執行,并引發更多異常。

嚴格模式在很多方面都有幫助:

  • 它捕獲了一些常見的編碼漏洞,并拋出異常。
  • 當采取相對不安全的操作(例如訪問全局對象)時,它可以防止錯誤或拋出錯誤。
  • 它禁用令人困惑或考慮不周到的特性。

另外,請注意,我信可以將“strict mode”應用于整個文件,也可以僅將其用于特定函數。

  1. // Non-strict code... 
  2.  
  3. (function(){ 
  4.   "use strict"
  5.  
  6.   // Define your library strictly... 
  7. })(); 
  8.  
  9. // Non-strict code...  

如果是在混合使用舊代碼和新代碼的情況,這可能會有所幫助。它有點像在Perl中使用的“use strict”。通過檢測更多可能導致損壞的東西,幫助我們減少更多的錯誤。

現在所有主流瀏覽器都支持嚴格模式。

在原生ECMAScript模塊(帶有import和export語句)和ES6類中,嚴格模式始終是啟用的,不能禁用。

5.如何檢查字符串是否包含子字符串?

ECMAScript 6 引入了string .prototype.include

  1. const string = "foo"
  2. const substring = "oo"
  3.  
  4. console.log(string.includes(substring)); 

不過,IE 不支持 includes。在 CMAScript 5或更早的環境中,使用String.prototype.indexOf。如果找不到子字符串,則返回-1:

  1. var string = "foo"
  2. var substring = "oo"
  3.  
  4. console.log(string.indexOf(substring) !== -1); 

為了使其在舊的瀏覽器中運行,可以使用這種polyfill:

  1. if (!String.prototype.includes) { 
  2.   String.prototype.includes = function(search, start) { 
  3.     'use strict'
  4.     if (typeof start !== 'number') { 
  5.       start = 0; 
  6.     } 
  7.  
  8.     if (start + search.length > this.length) { 
  9.       return false
  10.     } else { 
  11.       return this.indexOf(search, start) !== -1; 
  12.     } 
  13.   }; 

6. var functionName = function() {} 與 function functionName() {}

不同之處在于functionOne是一個函數表達式,因此只在到達這一行時才會定義,而functionTwo是一個函數聲明,在它周圍的函數或腳本被執行(由于提升)時就定義。

如,函數表達式

  1. // TypeError: functionOne is not a function 
  2. functionOne(); 
  3.  
  4. var functionOne = function() { 
  5.   console.log("Hello!"); 
  6. }; 

函數聲明:

  1. // "Hello!" 
  2. functionTwo(); 
  3.  
  4. function functionTwo() { 
  5.   console.log("Hello!"); 

過去,在不同的瀏覽器之間,在塊中定義的函數聲明的處理是不一致的。嚴格模式(在ES5中引入)解決了這個問題,它將函數聲明的范圍限定在其封閉的塊上。

  1. 'use strict';     
  2. { // note this block! 
  3.   function functionThree() { 
  4.     console.log("Hello!"); 
  5.   } 
  6. functionThree(); // ReferenceError 

function abc(){}也具有作用域-名稱abc在遇到該定義的作用域中定義。例:

  1. function xyz(){ 
  2.   function abc(){}; 
  3.   // abc 在這里定義... 
  4. // ...不是在這里 

如果想在所有瀏覽器上給函數起別名,可以這么做:

  1. function abc(){}; 
  2. var xyz = abc; 

在本例中,xyz和abc都是同一個對象的別名

  1. console.log(xyz === abc) // true 

它的名稱是自動分配的。但是當你定義它的時候

  1. var abc = function(){}; 
  2. console.log(abc.name); //  "" 

它的name稱為空,我們創建了一個匿名函數并將其分配給某個變量。使用組合樣式的另一個很好的理由是使用簡短的內部名稱來引用自身,同時為外部用戶提供一個長而不會沖突的名稱:

  1. // 假設 really.long.external.scoped 為 {} 
  2. really.long.external.scoped.name = function shortcut(n){ 
  3.   // 它遞歸地調用自己: 
  4.   shortcut(n - 1); 
  5.   // ... 
  6.   // 讓它自己作為回調傳遞:: 
  7.   someFunction(shortcut); 
  8.   // ... 

在上面的例子中,我們可以對外部名稱進行同樣的操作,但是這樣做太笨拙了(而且速度更慢)。另一種引用自身的方法是arguments.callee,這種寫法也相對較長,并且在嚴格模式中不受支持。

實際上,JavaScript對待這兩個語句是不同的。下面是一個函數聲明:

  1. function abc(){} 

這里的abc可以定義在當前作用域的任何地方:

  1. // 我們可以在這里調用 
  2. abc();  
  3.  
  4. // 在這里定義 
  5. function abc(){} 
  6.  
  7. // 也可以在這里調用  
  8. abc();  

此外,盡管有 return 語句,也可以提升:

  1. // 我們可以在這里調用 
  2. abc();  
  3. return
  4. function abc(){} 

下面是一個函數表達式:

  1. var xyz = function(){}; 

這里的xyz是從賦值點開始定義的:

  1. // 我們不可以在這里調用 
  2. xyz();  
  3.  
  4. // 在這里定義 xyz 
  5. xyz = function(){} 
  6.  
  7. // 我們可以在這里調用 
  8. xyz();  

函數聲明與函數表達式之間存在差異的真正原因。

  1. var xyz = function abc(){}; 
  2. console.log(xyz.name); // "abc" 

就個人而言,我們更喜歡使用函數表達式聲明,因為這樣可以控制可見性。當我們像這樣定義函數時:

  1. var abc = function(){}; 

我們知道,如果我們沒有在作用域鏈的任何地方定義abc,那么我們是在全局作用域內定義的。即使在eval()內部使用,這種類型的定義也具有彈性。而定義:

  1. function abc(){}; 

取決于上下文,并且可能讓你猜測它的實際定義位置,特別是在eval()的情況下,—取決于瀏覽器。

7.如何從 JavaScript 對象中刪除屬性?

我們可以這樣刪除對象的屬性:

  1. delete myObject.regex; 
  2. // 或者 
  3. delete myObject['regex']; 
  4. //  或者 
  5. var prop = "regex"
  6. delete myObject[prop]; 

事例:

  1. var myObject = { 
  2.     "ircEvent""PRIVMSG"
  3.     "method""newURI"
  4.     "regex""^http://.*" 
  5. }; 
  6. delete myObject.regex; 
  7.  
  8. console.log(myObject); 

JavaScript 中的對象可以看作鍵和值之間的映射。delete操作符用于一次刪除一個鍵(通常稱為對象屬性)。

  1. var obj = { 
  2.   myProperty: 1     
  3. console.log(obj.hasOwnProperty('myProperty')) // true 
  4. delete obj.myProperty 
  5. console.log(obj.hasOwnProperty('myProperty')) // false 

delete 操作符不是直接釋放內存,它不同于簡單地將null或undefined值賦給屬性,而是將屬性本身從對象中刪除。

注意,如果已刪除屬性的值是引用類型(對象),而程序的另一部分仍然持有對該對象的引用,那么該對象當然不會被垃圾收集,直到對它的所有引用都消失。

delete只對其描述符標記為configurable的屬性有效。

8. JS 的比較中應使用哪個等于運算符(== vs ===)?

嚴格相等運算符(===)的行為與抽象相等運算符(==)相同,除非不進行類型轉換,而且類型必須相同才能被認為是相等的。

==運算符會進行類型轉換后比較相等性。===運算符不會進行轉換,因此如果兩個值的類型不同,則===只會返回false。

JavaScript有兩組相等運算符:===和!==,以及它們的孿生兄弟==和!=。如果這兩個操作數具有相同的類型和相同的值,那么===的結果就是 true,而!==的結果就是 false。

下面是一些事例:

  1. '' == '0'           // false 
  2. 0 == ''             // true 
  3. 0 == '0'            // true 
  4.  
  5. false == 'false'    // false 
  6. false == '0'        // true 
  7.  
  8. false == undefined  // false 
  9. false == null       // false 
  10. null == undefined   // true 
  11.  
  12. ' \t\r\n ' == 0     // true 

上面有些看起來會挺困惑的,所以盡量還是使用嚴格比較運算符(===)。對于引用類型,==和===操作一致(特殊情況除外)。

  1. var a = [1,2,3]; 
  2. var b = [1,2,3]; 
  3.  
  4. var c = { x: 1, y: 2 }; 
  5. var d = { x: 1, y: 2 }; 
  6.  
  7. var e = "text"
  8. var f = "te" + "xt"
  9.  
  10. a == b            // false 
  11. a === b           // false 
  12.  
  13. c == d            // false 
  14. c === d           // false 
  15.  
  16. e == f            // true 
  17. e === f           // true 

特殊情況是,當你將一個字符串字面量與一個字符串對象進行比較時,由于該對象的toString或valueOf方法,該對象的值與相字面量的值一樣。

考慮將字符串字面量與由String構造函數創建的字符串對象進行比較:

  1. "abc" == new String("abc")    // true 
  2. "abc" === new String("abc")   // false 

在這里,==操作符檢查兩個對象的值并返回true,但是===看到它們不是同一類型并返回false。哪一個是正確的?這取決于你想要比較的是什么。

我們的建議是完全繞開該問題,只是不要使用String構造函數來創建字符串對象。

使用==運算符(等于)

  1. true == 1; //true, 因為 true 被轉換為1,然后進行比較 
  2. "2" == 2;  //true, 因為 “2” 被轉換成 2,然后進行比較 

使用===操作符

  1. true === 1; //false 
  2. "2" === 2;  //false 

9.在 JavaScript 中深拷貝一個對象的最有效方法是什么?

快速克隆,數據丟失– JSON.parse/stringify

如果您沒有在對象中使用Date、函數、undefined、Infinity、RegExp、Map、Set、blob、、稀疏數組、類型化數組或其他復雜類型,那么可以使用一行簡單代碼來深拷貝一個對象:

  1. JSON.parse(JSON.stringify(object)) 
  2. const a = { 
  3.   string: 'string'
  4.   number: 123, 
  5.   bool: false
  6.   nul: null
  7.   date: new Date(),  
  8.   undef: undefined,  // 丟失 
  9.   inf: Infinity,  // 被設置為 null 
  10.   re: /.*/,  // 丟失 
  11. console.log(a); 
  12. console.log(typeof a.date);  // object 
  13. const clone = JSON.parse(JSON.stringify(a)); 
  14. console.log(clone); 
  15. /* 
  16. object 
  17.   string: 'string'
  18.   number: 123, 
  19.   bool: false
  20.   nul: null
  21.   date'2020-09-04T00:45:41.823Z'
  22.   inf: null
  23.   re: {} 
  24.  
  25. */ 
  26. console.log(typeof clone.date);  // string 

使用庫進行可靠的克隆

由于克隆對象不是一件簡單的事情(復雜類型、循環引用、函數等等),大多數主要的庫都提供了拷貝對象的函數。如果你已經在使用一個庫,請檢查它是否具有對象克隆功能。例如

  • lodash – cloneDeep; 可以通過lodash.clonedeep模塊單獨導入,如果你尚未使用提供深拷貝功能的庫,那么它可能是你的最佳選擇
  • AngularJS – angular.copy
  • jQuery – jQuery.extend(true, { }, oldObject); .clone()僅克隆DOM元素

ES6

ES6 提供了兩種淺拷貝機制:Object.assign()和spread語法。它將所有可枚舉的自有屬性的值從一個對象復制到另一個對象。例如

  1. var A1 = {a: "2"}; 
  2. var A2 = Object.assign({}, A1); 
  3. var A3 = {...A1};  // Spread Syntax 

在以前的測試中,速度是最主要的問題

  1. JSON.parse(JSON.stringify(obj)) 

這是深拷貝對象的最慢方法,它比jQuery.extend慢 10-20%。

當deep標志設置為false(淺克隆)時,jQuery.extend非??臁_@是一個不錯的選擇,因為它包括一些用于類型驗證的額外邏輯,并且不會復制未定義的屬性等,但這也會使你的速度變慢。

如果想拷貝的一個對象且你知道對象結構。那么,你可以寫一個簡單的for (var i in obj)循環來克隆你的對象,同時檢查hasOwnProperty,這將比jQuery快得多。

  1. var clonedObject = { 
  2.   knownProp: obj.knownProp, 
  3.   .. 

注意在 Date 對象JSON上使用JSON.parse(JSON.stringify(obj))方法。JSON.stringify(new Date())以ISO格式返回日期的字符串表示,JSON.parse()不會將其轉換回Date對象。

10.如何在另一個JavaScript文件中包含一個JavaScript文件?

舊版本的JavaScript沒有import、include或require,因此針對這個問題開發了許多不同的方法。

但是從2015年(ES6)開始,JavaScript已經有了ES6模塊標準,可以在Node中導入模塊。為了與舊版瀏覽器兼容,可以使用Webpack和Rollup之類的構建工具和/或Babel這樣的編譯工具。

ES6 Module

從v8.5開始,Node.js就支持ECMAScript (ES6)模塊,帶有--experimental-modules標志,而且至少Node.js v13.8.0沒有這個標志。要啟用ESM(相對于Node.js之前的commonjs風格的模塊系統[CJS]),你可以在 package.json中使用“type”:“module”。或者為文件提供擴展名.mjs。(類似地,如果默認為ESM,則用 Node.js 以前的CJS模塊編寫的模塊可以命名為.cjs。)

使用package.json:

  1.     "type""module" 

在 module.js: 中

  1. export function hello() { 
  2.   return "Hello"

main.js:

  1. import { hello } from './module.js'
  2. let val = hello();  // val is "Hello"

使用.mjs,會有對應的module.mjs:

  1. export function hello() { 
  2.   return "Hello"

在main.mjs 中

  1. import { hello } from './module.mjs'
  2. let val = hello();  // val is "Hello"

自Safari 10.1,Chrome 61,Firefox 60 和 Edge 16 開始,瀏覽器就已經支持直接加載ECMAScript模塊(不需要像Webpack這樣的工具)。無需使用Node.js的.mjs擴展名;瀏覽器完全忽略模塊/腳本上的文件擴展名。

  1. <script type="module"
  2.   import { hello } from './hello.mjs'; // Or it could be simply `hello.js` 
  3.   hello('world'); 
  4. </script> 
  5. // hello.mjs -- or it could be simply `hello.js` 
  6. export function hello(text) { 
  7.   const div = document.createElement('div'); 
  8.   div.textContent = `Hello ${text}`; 
  9.   document.body.appendChild(div); 

瀏覽器中的動態導入

動態導入允許腳本根據需要加載其他腳本

  1. <script type="module"
  2.   import('hello.mjs').then(module => { 
  3.       module.hello('world'); 
  4.     }); 
  5. </script> 

 

Node.js require

在 Node.js 中用的較多還是 module.exports/require

  1. // mymodule.js 
  2. module.exports = { 
  3.    hello: function() { 
  4.       return "Hello"
  5.    } 

// server.js const myModule = require('./mymodule'); let val = myModule.hello(); // val is "Hello"

動態加載文件

我們可以通過動態創建 script 來動態引入文件:

  1. function dynamicallyLoadScript(url) { 
  2.     var script = document.createElement("script");  
  3.  
  4.     document.head.appendChild(script);  

檢測腳本何時執行

現在,有一個個大問題。上面這種動態加載都是異步執行的,這樣可以提高網頁的性能。這意味著不能在動態加載下馬上使用該資源,因為它可能還在加載。

例如:my_lovely_script.js包含MySuperObject:

  1. var js = document.createElement("script"); 
  2.  
  3. js.type = "text/javascript"
  4. js.src = jsFilePath; 
  5.  
  6. document.body.appendChild(js); 
  7.  
  8. var s = new MySuperObject(); 
  9.  
  10. Error : MySuperObject is undefined 

然后,按F5重新加載頁面,可能就有效了。那么該怎么辦呢?

我們可以使用回調函數來解決些問題。

  1. function loadScript(url, callback) 
  2.     var head = document.head; 
  3.     var script = document.createElement('script'); 
  4.     script.type = 'text/javascript'
  5.     script.src = url; 
  6.  
  7.     script.onload = callback; 
  8.  
  9.     head.appendChild(script); 

然后編寫在lambda函數中加載腳本后要使用的代碼

  1. var myPrettyCode = function() { 
  2.    // Here, do whatever you want 
  3. }; 

然后,運行代碼:

  1. loadScript("my_lovely_script.js", myPrettyCode); 

 

請注意,腳本可能在加載DOM之后或之前執行,具體取決于瀏覽器以及是否包括行script.async = false;。

本文轉載自微信公眾號「大遷世界」,可以通過以下二維碼關注。轉載本文請聯系大遷世界公眾號。

 

責任編輯:武曉燕 來源: 大遷世界
相關推薦

2013-08-21 09:57:50

虛擬化技巧

2024-08-13 15:09:41

2024-03-27 08:36:48

JavaScriptWeb開發前端開發

2020-08-06 08:27:21

JavaScript概念語言

2017-11-21 14:42:30

數據科學統計學習機器學習

2022-08-12 09:21:43

前端JavaScript代碼

2022-04-26 18:33:02

JavaScript技巧代碼

2021-01-21 17:17:47

前端開發語言

2017-05-27 15:21:38

JavaScript機器學習示例

2010-09-02 16:14:20

CSS布局

2015-07-15 13:34:37

JS開發習慣

2010-08-02 16:20:31

ICMP協議

2010-01-04 16:16:31

JavaScript語

2010-09-01 09:23:53

DIV CSS

2019-11-01 14:22:31

云計算物聯網邊緣計算

2025-02-06 18:27:10

2010-09-10 12:13:07

網絡協議學習

2017-07-27 15:05:18

前端JavaScript難點

2023-08-02 18:44:47

JavaScript命名web

2011-02-17 14:43:29

Windows 7加速
點贊
收藏

51CTO技術棧公眾號

日本在线观看一区二区| 91精品国产91久久久久久| 色噜噜狠狠一区二区| 欧美成年黄网站色视频| 国产不卡视频在线播放| 97在线日本国产| 青青草自拍偷拍| y111111国产精品久久久| 黑人欧美xxxx| 亚洲自拍偷拍二区| 天天干在线观看| 麻豆91在线播放| 97超碰国产精品女人人人爽| 日本美女黄色一级片| 欧美美女黄色| 欧美一级高清片| 凹凸日日摸日日碰夜夜爽1| 岛国中文字幕在线| 久久久亚洲午夜电影| 99伊人久久| 中文字幕视频在线播放| 亚洲国产精品一区制服丝袜| 日韩一区二区欧美| 99久久久无码国产精品性 | 亚洲综合色av| 最新在线中文字幕| 国产精品入口66mio| 欧美成人免费一级人片100| 国产综合精品久久久久成人av| 国产精品色呦| 日韩一区二区免费高清| 污色网站在线观看| 日韩pacopacomama| 亚洲国产精品人人做人人爽| 熟女视频一区二区三区| 91精品专区| 国产日产欧美一区| 另类欧美小说| 亚洲人在线观看视频| 国产一区中文字幕| 成人网在线免费观看| 中国女人真人一级毛片| 日韩精品一二区| 国产97在线视频| 亚洲精品男人天堂| 亚洲一区二区免费看| 久久久亚洲欧洲日产国码aⅴ| 国产高潮国产高潮久久久91| 欧美国产美女| 日韩视频中文字幕| www.xx日本| 99久久久久国产精品| 中文字幕不卡av| 成人做爰69片免网站| 精品99在线| 一区二区欧美日韩视频| 亚洲精品国产91| av伊人久久| 在线视频日韩精品| www.黄色com| 欧美一区二区三区久久精品茉莉花| 日韩最新中文字幕电影免费看| 国产黄a三级三级| 在线精品视频在线观看高清| 欧美激情高清视频| 日韩乱码在线观看| 久久国产精品亚洲77777| 国产成人久久久| 91亚洲欧美激情| 国产精品一区三区| 国产综合动作在线观看| 免费在线观看污视频| 中文字幕乱码亚洲精品一区| 亚洲精品中文字幕在线| 黄色网在线播放| 亚洲第一主播视频| 少妇高潮喷水久久久久久久久久| 桃子视频成人app| 欧美日韩高清一区二区不卡| 欧美高清精品一区二区| 久草精品视频| 亚洲香蕉伊综合在人在线视看| 国产成人精品视频免费| 午夜精品视频| 日本aⅴ大伊香蕉精品视频| 91免费视频播放| 国产91丝袜在线观看| 免费毛片一区二区三区久久久| 国产高清一级毛片在线不卡| 亚洲三级久久久| 欧美日韩一道本| 久久影视精品| 亚洲第一精品夜夜躁人人躁 | 国内精品国产成人国产三级| 97se亚洲国产综合自在线 | 欧美成人有码| 青青久久aⅴ北条麻妃| 国产又粗又猛又爽又黄的视频一| 床上的激情91.| 视频一区二区在线| bl视频在线免费观看| 欧美撒尿777hd撒尿| 折磨小男生性器羞耻的故事| 日韩欧美国产精品综合嫩v| 欧美激情啊啊啊| 国产一区二区波多野结衣| 99riav久久精品riav| 99精品一级欧美片免费播放| 日韩成人影音| 亚洲国产毛片完整版| 福利视频第一页| 石原莉奈一区二区三区在线观看| 999热视频| аⅴ资源新版在线天堂| 午夜电影网一区| 伊人影院在线观看视频| 波多野结衣的一区二区三区 | 亚洲天堂av综合网| 国产一级视频在线观看| 久久精品国产网站| 欧美重口乱码一区二区| а√天堂资源官网在线资源| 日韩一卡二卡三卡四卡| 日韩欧美黄色网址| 美日韩精品视频| 成人免费视频网站| 大片免费在线观看| 欧美高清性hdvideosex| 微拍福利一区二区| 免费亚洲一区| 久久99精品国产99久久| free性护士videos欧美| 日韩欧美你懂的| 国产一区二区视频在线观看免费| 男女性色大片免费观看一区二区 | 性高潮久久久久久| 爽成人777777婷婷| 国产精品久久视频| 成人精品一区| 欧美在线影院一区二区| 亚洲AV无码片久久精品| 久久xxxx| 欧美亚洲一级二级| 亚洲欧洲高清| 日韩精品中文字幕在线观看| 日韩欧美亚洲视频| 成人白浆超碰人人人人| 成年人深夜视频| 中文字幕一区日韩精品| 欧美激情视频在线免费观看 欧美视频免费一 | 川上优av一区二区线观看| 福利在线视频导航| 在线观看不卡一区| 免费一级黄色录像| 久88久久88久久久| 国产欧美自拍视频| 中文字幕一区二区三区日韩精品| 欧美精品成人在线| 五月婷婷在线播放| 香蕉成人啪国产精品视频综合网| 制服丝袜第一页在线观看| 亚洲精品极品| 欧美高清视频一区| 欧美日韩在线精品一区二区三区激情综合| 亚洲一区二区久久| 国产又粗又猛又黄| 亚洲精品国产无天堂网2021| av天堂一区二区| 久久国产成人| 一区二区在线观看网站| 欧美高清hd| 韩国精品久久久999| 青青草娱乐在线| 欧美日韩久久一区| 极品盗摄国产盗摄合集| 成人国产精品免费| 成年人免费大片| 欧美激情另类| 国产乱人伦精品一区二区| 亚洲校园激情春色| 日韩亚洲欧美成人| 网站黄在线观看| 欧美午夜一区二区三区| 欧美日韩成人免费观看| 91免费视频网址| 五月激情婷婷在线| 在线视频观看日韩| 一区二区在线高清视频| 麻豆成人入口| 成人黄色网免费| 国产精品一区二区日韩| 最近2019中文字幕第三页视频| 黄色一级大片在线免费看国产一| 色又黄又爽网站www久久| 91视频综合网| 久久综合色8888| 91热视频在线观看| 男女av一区三区二区色多| 手机成人av在线| 亚洲动漫精品| 成人av影视在线| 成人免费黄色| 51久久精品夜色国产麻豆| 蜜桃视频网站在线| 亚洲欧洲激情在线| 好男人在线视频www| 欧美日韩一区三区| 久久久久久久久久影院| 亚洲精品写真福利| 日韩不卡av在线| 99精品欧美一区二区三区综合在线| 色婷婷综合网站| 亚洲一区日韩在线| www.成年人视频| 香蕉国产精品| 色播亚洲婷婷| 日韩深夜影院| 国产另类自拍| 日韩三级不卡| 91免费看国产| 99热播精品免费| 国产成人一区二| 爱情电影社保片一区| 国内精品中文字幕| 久久www人成免费看片中文| 日韩在线视频观看正片免费网站| 全部免费毛片在线播放网站| 欧美精品一区二区三区蜜桃视频 | 99久久综合国产精品| 91亚洲一区二区| 精品亚洲欧美一区| 自拍偷拍21p| 免费美女久久99| 精品久久久久久久无码| 亚洲影视在线| 男人和女人啪啪网站| 精品999成人| 日韩精品一区二区三区四| 一区二区日韩欧美| 美女在线免费视频| 综合天堂av久久久久久久| 中文字幕中文字幕在线中一区高清| 国语产色综合| 日韩国产在线一区| 成人高清av| 亚洲一区二区三区免费观看| 日韩精品一区二区三区免费观看| 天堂一区二区三区| 日韩大片在线观看| 亚洲欧美日韩国产yyy| 日韩欧美视频在线播放| 亚洲v欧美v另类v综合v日韩v| 欧洲乱码伦视频免费| 一区二区不卡视频| 欧美黄色一区| 日本免费a视频| 99精品免费网| 日韩精品一区中文字幕| 蜜臀av亚洲一区中文字幕| 91女神在线观看| 国产一区二区三区在线观看免费视频| 日本网站在线看| 粉嫩绯色av一区二区在线观看| bl动漫在线观看| 国产女主播视频一区二区| 国产18无套直看片| 成人免费在线视频| 久久久久亚洲av无码专区| 午夜成人免费电影| 黄色av一区二区| 91精品欧美综合在线观看最新| 亚洲国产一二三区| 亚洲精品福利在线观看| 超碰免费在线| 久久99国产综合精品女同| 国产美女精品写真福利视频| 热久久这里只有| 精品视频在线观看免费观看| 精品久久sese| 国产精品久久久久无码av| 国产欧美精品aaaaaa片| 老司机一区二区三区| 成人免费黄色av| 91尤物视频在线观看| 亚洲一二三四五六区| 亚洲动漫第一页| 在线免费观看av片| 精品国产一区二区精华| 成人影院免费观看| 美日韩精品免费观看视频| 一区二区三区四区日本视频| 91精品久久久久久久久青青 | 成人在线视频免费| 粉嫩av免费一区二区三区| 精品美女视频| 大西瓜av在线| 麻豆一区二区三区| 亚洲制服丝袜在线播放| 综合精品久久久| 一级成人黄色片| 精品国产一区二区三区四区四 | 久草在线成人| 久久人妻无码一区二区| 日韩精品三区四区| 亚洲色偷偷色噜噜狠狠99网| 国产精品伦一区二区三级视频| 日韩黄色三级视频| 在线91免费看| 国产在线自天天| …久久精品99久久香蕉国产| 成人久久精品| 少妇精品久久久久久久久久| aⅴ色国产欧美| 中文字幕制服丝袜| 中文字幕日本不卡| 中文字幕码精品视频网站| 亚洲精品美女在线| 久草在线资源站资源站| 91亚洲国产成人精品性色| 欧美日韩激情| 久久久久久久久久久久久国产精品| 成人一二三区视频| 黄色一级视频免费观看| 欧美高清视频www夜色资源网| 国产资源在线观看| 琪琪第一精品导航| 性欧美lx╳lx╳| aa在线观看视频| 成人免费av在线| 国产亚洲第一页| 日韩三级中文字幕| a级在线观看| 91亚洲精品久久久久久久久久久久| 久久国产精品亚洲人一区二区三区 | sm捆绑调教视频| 欧美视频一区二区在线观看| 可以在线观看的av| 日本不卡免费高清视频| 久久99性xxx老妇胖精品| 国产又黄又大又粗视频| 91亚洲资源网| 国产精品久久久久久人| 精品视频久久久久久| 亚洲精品日产| 欧美在线3区| 免费观看日韩电影| 亚洲欧美综合7777色婷婷| 精品视频1区2区3区| 在线观看国产原创自拍视频| 成人精品福利视频| 在线一区电影| www.555国产精品免费| 亚洲高清免费在线| 午夜在线视频观看| 日韩免费在线观看视频| 青青草成人影院| 老司机久久精品| 亚洲综合自拍偷拍| 熟妇人妻一区二区三区四区| 69视频在线免费观看| 亚洲宅男网av| 嫩草影院国产精品| 一区二区中文字幕在线| 精品人妻无码一区二区| 97国产精品免费视频| 国产va免费精品观看精品视频| 天天爽人人爽夜夜爽| 亚洲图片激情小说| 可以免费看毛片的网站| 亲爱的老师9免费观看全集电视剧| 欧美伦理影院| 亚洲欧美日韩中文字幕在线观看| 亚洲国产一区二区a毛片| 无码国产色欲xxxx视频| 国产精品第一第二| 欧美一区国产在线| 国产艳俗歌舞表演hd| 欧美精品久久久久久久久老牛影院| 国产黄色在线网站| 久久久国产精品一区二区三区| 日产国产高清一区二区三区| 欧美日韩在线观看成人| 日韩国产在线看| 日日夜夜亚洲| 成人中文字幕在线播放| 欧美国产欧美综合| 亚洲精品18p| 国产精品久久久久久久久久小说| 欧美96在线丨欧| 欧美性猛交xxxx乱| 日韩你懂的在线播放| 欧美xxx网站| 污污污污污污www网站免费| 久久免费看少妇高潮| av加勒比在线| 国产精品极品尤物在线观看 | 青青草原国产在线视频| 亚洲丰满少妇videoshd| 黄网站在线播放| 鲁丝片一区二区三区|