這是我參與更文挑戰的第27天,活動詳情查看: 更文挑戰javascript
14萬字 | 400 多道 JavaScript 面試題 🎓 有答案 🌠(第一部分 1-100題)html
14萬字 | 400 多道 JavaScript 面試題 🎓 有答案 🌠(第二部分 101-200題)java
14萬字 | 400 多道 JavaScript 面試題 🎓 有答案 🌠(第三部分 201-300題)node
14萬字 | 400 多道 JavaScript 面試題 🎓 有答案 🌠(第四部分 301-370題)react
14萬字 | 400 多道 JavaScript 面試題 🎓 有答案 🌠(第五部分 371-424題)web
爲了方便手機閱覽,我在必要位置都放了回頂部或者回對應問題的連接面試
有不少方法能夠在 javascript 中建立對象,以下所示正則表達式
建立空對象的最簡單方法是使用 Object 構造函數。目前不推薦這種方法。typescript
var object = new Object();
複製代碼
Object 的 create 方法經過將原型對象做爲參數傳遞來建立一個新對象shell
var object = Object.create(null);
複製代碼
當傳遞 null 做爲參數時,對象字面量語法等效於 create 方法
var object = {};
複製代碼
建立任何函數並應用 new 運算符來建立對象實例,
function Person(name){
var object = {};
object.name=name;
object.age=21;
return object;
}
var object = new Person("Sudheer");
複製代碼
這相似於函數構造函數,但它使用原型做爲其屬性和方法,
function Person(){}
Person.prototype.name = "Sudheer";
var object = new Person();
複製代碼
這等效於使用具備函數原型的對象建立方法建立的實例,而後使用實例和參數做爲參數調用該函數。
function func {};
new func(x, y, z);
複製代碼
(或者)
// 使用函數原型建立一個新實例。
var newInstance = Object.create(func.prototype)
// 調用函數
var result = func.call(newInstance, x, y, z),
// 若是結果是非空對象,則使用它,不然只使用新實例。
console.log(result && typeof result === 'object' ? result : newInstance);
複製代碼
ES6 引入類特性來建立對象
class Person {
constructor(name) {
this.name = name;
}
}
var object = new Person("Sudheer");
複製代碼
Singleton 是一個只能實例化一次的對象。對其構造函數的重複調用返回相同的實例,這樣能夠確保它們不會意外建立多個實例。
var object = new function(){
this.name = "Sudheer";
}
複製代碼
原型鏈用於基於現有對象構建新類型的對象。它相似於基於類的語言中的繼承。
對象實例上的原型可經過Object.getPrototypeOf(object)
或proto
屬性得到,而構造函數上的原型可經過Object.prototype
得到。
Call、Apply 和 Bind 之間的區別能夠用下面的例子來解釋,
call: call() 方法調用一個函數,給定的this值和參數一一提供
var employee1 = {firstName: 'Haiyong', lastName: 'Rodson'};
var employee2 = {firstName: 'Jimmy', lastName: 'Baily'};
function invite(greeting1, greeting2) {
console.log(greeting1 + ' ' + this.firstName + ' ' + this.lastName+ ', '+ greeting2);
}
invite.call(employee1, 'Hello', 'How are you?'); // Hello Haiyong Rodson, How are you?
invite.call(employee2, 'Hello', 'How are you?'); // Hello Jimmy Baily, How are you?
複製代碼
apply:調用具備給定this值的函數,並容許你將參數做爲數組傳入
var employee1 = {firstName: 'Haiyong', lastName: 'Rodson'};
var employee2 = {firstName: 'Jimmy', lastName: 'Baily'};
function invite(greeting1, greeting2) {
console.log(greeting1 + ' ' + this.firstName + ' ' + this.lastName+ ', '+ greeting2);
}
invite.apply(employee1, ['Hello', 'How are you?']); // Hello Haiyong Rodson, How are you?
invite.apply(employee2, ['Hello', 'How are you?']); // Hello Jimmy Baily, How are you?
複製代碼
bind:返回一個新函數,容許你傳遞任意數量的參數
var employee1 = {firstName: 'Haiyong', lastName: 'Rodson'};
var employee2 = {firstName: 'Jimmy', lastName: 'Baily'};
function invite(greeting1, greeting2) {
console.log(greeting1 + ' ' + this.firstName + ' ' + this.lastName+ ', '+ greeting2);
}
var inviteEmployee1 = invite.bind(employee1);
var inviteEmployee2 = invite.bind(employee2);
inviteEmployee1('Hello', 'How are you?'); // Hello Haiyong Rodson, How are you?
inviteEmployee2('Hello', 'How are you?'); // Hello Jimmy Baily, How are you?
複製代碼
Call 和 apply 能夠互換。二者都當即執行當前函數。你須要決定是發送數組仍是逗號分隔的參數列表更容易。你能夠經過處理 Call 用於逗號(分隔列表)和 Apply 用於Array來記住。
而 Bind 建立一個新函數,該函數將this設置爲傳遞給 bind() 的第一個參數。
JSON是一種基於文本的數據格式,遵循 JavaScript 對象語法,由道格拉斯·克羅克福德 (Douglas Crockford) 推行。 當你想經過網絡傳輸數據時它頗有用,它基本上只是一個擴展名爲 .json 的文本文件,以及一個 MIME 類型的 application/json
解析:將字符串轉換爲原生對象
JSON.parse(text)
複製代碼
字符串化:將本機對象轉換爲字符串,以即可以經過網絡傳輸
JSON.stringify(object)
複製代碼
所述slice()
方法返回在數組做爲新的數組對象中選定的元件。它選擇從給定開始參數開始的元素,並在給定的可選結束參數處結束,不包括最後一個元素。若是省略第二個參數,則它會一直選擇到最後。
這種方法的一些例子是,
let arrayIntegers = [1, 2, 3, 4, 5];
let arrayIntegers1 = arrayIntegers.slice(0,2); // returns [1,2]
let arrayIntegers2 = arrayIntegers.slice(2,3); // returns [3]
let arrayIntegers3 = arrayIntegers.slice(4); //returns [5]
複製代碼
==注意==: Slice 方法不會改變原始數組,而是將子集做爲新數組返回。
splice() 方法用於向/從數組添加/刪除項目,而後返回被刪除的項目。第一個參數指定插入或刪除的數組位置,而選項第二個參數指示要刪除的元素數。每一個附加參數都添加到數組中。
這種方法的一些例子是,
let arrayIntegersOriginal1 = [1, 2, 3, 4, 5];
let arrayIntegersOriginal2 = [1, 2, 3, 4, 5];
let arrayIntegersOriginal3 = [1, 2, 3, 4, 5];
let arrayIntegers1 = arrayIntegersOriginal1.splice(0,2); // returns [1, 2]; original array: [3, 4, 5]
let arrayIntegers2 = arrayIntegersOriginal2.splice(3); // returns [4, 5]; original array: [1, 2, 3]
let arrayIntegers3 = arrayIntegersOriginal3.splice(3, 1, "a", "b", "c"); //returns [4]; original array: [1, 2, 3, "a", "b", "c", 5]
複製代碼
==注意==: Splice 方法修改原始數組並返回刪除的數組。
表格形式的一些主要區別
slice() | splice() |
---|---|
不修改原始數組(不可變) | 修改原始數組(可變) |
返回原始數組的子集 | 將刪除的元素做爲數組返回 |
用於從數組中選取元素 | 用於在數組中插入或刪除元素 |
Object 與Maps 的類似之處在於,它們都容許您將鍵設置爲值、檢索這些值、刪除鍵以及檢測某個鍵是否存儲了某些內容。因爲這個緣由,對象在歷史上被用做地圖。可是在某些狀況下,使用 Map 有一些重要的區別。
map =Object.create(null)
繞過,但不多這樣作。JavaScript 提供了嚴格(===, !==
) 和類型轉換(==, !=
) 相等比較。嚴格運算符考慮變量的類型,而非嚴格運算符根據變量的值進行類型校訂/轉換。嚴格的運算符遵循如下不一樣類型的條件,
NaN 不等於任何東西,包括 NaN。
正零和負零彼此相等。
===
不相等,但與 ==
相等。即, null===undefined --> false
但 null==undefined --> true
一些涵蓋上述狀況的例子,
0 == false // true
0 === false // false
1 == "1" // true
1 === "1" // false
null == undefined // true
null === undefined // false
'0' == false // true
'0' === false // false
[]==[] or []===[] //false, refer different objects in memory
{}=={} or {}==={} //false, refer different objects in memory
複製代碼
箭頭函數是函數表達式的較短語法,沒有本身的this、arguments、super 或 new.target。這些函數最適合非方法函數,它們不能用做構造函數。
在 Javascript 中,函數是第一類對象。頭等函數意味着該語言中的函數被視爲任何其餘變量。
例如,在這種語言中,一個函數能夠做爲參數傳遞給其餘函數,能夠由另外一個函數返回,也能夠做爲一個值分配給一個變量。例如,在下面的示例中,分配給偵聽器的處理函數
const handler = () => console.log ('This is a click handler function');
document.addEventListener ('click', handler);
複製代碼
一階函數是不接受另外一個函數做爲參數而且不返回函數做爲其返回值的函數。
const firstOrder = () => console.log ('I am a first order function!');
複製代碼
高階函數是接受另外一個函數做爲參數或返回一個函數做爲返回值或二者兼而有之的函數。
const firstOrderFunc = () => console.log ('Hello, I am a First order function');
const higherOrder = ReturnFirstOrderFunc => ReturnFirstOrderFunc();
higherOrder(firstOrderFunc);
複製代碼
一元函數(即 monadic)是一個只接受一個參數的函數。它表明一個函數接受的單個參數。
讓咱們以一元函數爲例,
const unaryFunction = a => console.log (a + 10); // 給給定的參數加 10
複製代碼
柯里化是將具備多個參數的函數轉換爲每一個只有一個參數的函數序列的過程。Currying 以數學家Haskell Curry 的名字命名。經過應用柯里化,n 元函數將其變成一元函數。
讓咱們舉一個 n-ary 函數的例子,以及它如何變成一個柯里化函數,
const multiArgFunction = (a, b, c) => a + b + c;
console.log(multiArgFunction(1,2,3));// 6
const curryUnaryFunction = a => b => c => a + b + c;
curryUnaryFunction (1); // return a function: b => c => 1 + b + c
curryUnaryFunction (1) (2); // return a function: c => 3 + c
curryUnaryFunction (1) (2) (3); // return 數字 6
複製代碼
Curried 函數對於提升代碼複用性和函數組合很是有用。
一個純函數是在返回值是由它的參數沒有任何反作用只有肯定的函數。即若是您在應用程序中調用具備相同參數 'n' 次和 'n' 個位置的函數,則它將始終返回相同的值。
咱們舉個例子來看看純函數和非純函數的區別,
//不純
let numberArray = [];
const impureAddNumber = number => numberArray.push(number);
//純
const pureAddNumber = number => argNumberArray =>
argNumberArray.concat([number]);
//顯示結果
console.log (impureAddNumber(6)); // returns 1
console.log (numberArray); // returns [6]
console.log (pureAddNumber(7) (numberArray)); // returns [6, 7]
console.log (numberArray); // returns [6]
複製代碼
根據上面的代碼片斷,經過改變數組並返回一個與參數值無關的推送數字索引,推送函數自己是不純的。而另外一方面,Concat獲取數組並將其與另外一個數組鏈接起來,產生一個沒有反作用的全新數組。此外,返回值是前一個數組的串聯。
請記住,純函數很重要,由於它們簡化了單元測試,沒有任何反作用,也不須要依賴注入。它們還避免了緊密耦合,並經過沒有任何反作用使您的應用程序更難中斷。這些原則經過優先使用const 而不是let與 ES6 的不變性概念結合在一塊兒。
let語句聲明瞭一個塊做用域局部變量。所以,使用 let 關鍵字定義的變量的範圍僅限於使用它的塊、語句或表達式。而使用var關鍵字聲明的變量用於定義全局變量或局部變量,而無論塊做用域如何。
咱們舉個例子來演示一下用法,
let counter = 30;
if (counter === 30) {
let counter = 31;
console.log(counter); // 31
}
console.log(counter); // 30 (由於這裏不存在 if 塊中的變量)
複製代碼
以表格格式列出差別
var | let |
---|---|
它從 JavaScript 開始就可用 | 做爲 ES6 的一部分引入 |
它有函數做用域 | 它有塊做用域 |
變量將被提高 | 已提高但未初始化 |
讓咱們舉個例子看看區別, |
function userDetails(username) {
if(username) {
console.log(salary); // 因爲變量提高未定義
console.log(age); // 參考錯誤:初始化前沒法訪問"age"
let age = 30;
var salary = 10000;
}
console.log(salary); //10000 (可訪問到適當的函數範圍)
console.log(age); //error:age未定義(因爲塊做用域)
}
userDetails('Haiyong');
複製代碼
let
是一種數學語句,被早期的編程語言如Scheme和Basic 所採用。它是從數十種其餘語言中借用而來的,這些語言let已經儘量地做爲傳統關鍵字使用var。
若是您嘗試在 a 中從新聲明變量,switch block則會致使錯誤,由於只有一個塊。例如,下面的代碼塊拋出以下語法錯誤,
let counter = 1;
switch(x) {
case 0:
let name;
break;
case 1:
let name; // 從新聲明的語法錯誤。
break;
}
複製代碼
爲避免此錯誤,您能夠在 case 子句中建立一個嵌套塊並建立一個新的塊範圍詞法環境。
let counter = 1;
switch(x) {
case 0: {
let name;
break;
}
case 1: {
let name; // 沒有用於從新聲明的 SyntaxError。
break;
}
}
複製代碼
暫時性死區是 JavaScript 中的一種行爲,在使用 let 和 const 關鍵字聲明變量時發生,但不使用 var 聲明變量。在 ECMAScript 6 中,在其聲明以前(在其範圍內)訪問letorconst變量會致使 ReferenceError。發生這種狀況的時間跨度,即變量綁定的建立和聲明之間,稱爲時間死區。
讓咱們用一個例子來看看這個行爲,
function somemethod() {
console.log(counter1); // undefined
console.log(counter2); // ReferenceError
var counter1 = 1;
let counter2 = 2;
}
複製代碼
IIFE(當即調用函數表達式)是一個 JavaScript 函數,它在定義後當即運行。它的簽名以下,
(function () {
// 在這裏寫邏輯
}
)
();
複製代碼
使用 IIFE 的主要緣由是爲了得到數據隱私,由於在 IIFE 中聲明的任何變量都不能被外界訪問。即,若是您嘗試使用 IIFE 訪問變量,則會引起以下錯誤,
(function () {
var message = "IIFE";
console.log(message);
}
)
();
console.log(message); //Error: message is not defined(消息未定義)
複製代碼
使用模塊有利於擴展有不少好處。其中一些好處是,
Memoization 是一種編程技術,它試圖經過緩存先前計算的結果來提升函數的性能。每次調用 memoized 函數時,都會使用其參數來索引緩存。若是數據存在,則能夠返回它,而無需執行整個函數。不然執行該函數,而後將結果添加到緩存中。
讓咱們舉一個添加記憶化功能的例子,
const memoizAddition = () => {
let cache = {};
return (value) => {
if (value in cache) {
console.log('Fetching from cache');
return cache[value]; // 在這裏, cache.value 不能用做以數字開頭的屬性名稱,該數字不是有效的 JavaScript 標識符。 所以,只能使用方括號表示法訪問。
}
else {
console.log('Calculating result');
let result = value + 20;
cache[value] = result;
return result;
}
}
}
// memoizAddition 返回的函數
const addition = memoizAddition();
console.log(addition(20)); //輸出: 40 calculated
console.log(addition(20)); //輸出: 40 cached
複製代碼
Hoisting是一種 JavaScript 機制,其中變量和函數聲明在代碼執行以前被移動到其做用域的頂部。請記住,JavaScript 只提高聲明,而不是初始化。 咱們舉一個簡單的變量提高的例子,
console.log(message); //輸出: undefined
var message = 'The variable Has been hoisted';
複製代碼
上面的代碼看起來像下面的解釋器,
var message;
console.log(message);
message = 'The variable Has been hoisted';
複製代碼
在 ES6 中,Javascript 類主要是對 JavaScript 現有的基於原型的繼承的語法糖。
例如,在函數表達式中編寫的基於原型的繼承以下,
function Bike(model,color) {
this.model = model;
this.color = color;
}
Bike.prototype.getDetails = function() {
return this.model + ' bike has' + this.color + ' color';
};
複製代碼
而 ES6 類能夠定義爲替代
class Bike{
constructor(color, model) {
this.color= color;
this.model= model;
}
getDetails() {
return this.model + ' bike has' + this.color + ' color';
}
}
複製代碼
閉包是函數和聲明該函數的詞法環境的組合。即,它是一個內部函數,能夠訪問外部或封閉函數的變量。閉包有三個做用域鏈
讓咱們舉一個閉包概念的例子,
function Welcome(name){
var greetingInfo = function(message){
console.log(message+' '+name);
}
return greetingInfo;
}
var myFunction = Welcome('Haiyong');
myFunction('Welcome '); //輸出: Welcome Haiyong
myFunction('Hello Mr.'); //輸出: Hello Mr.Haiyong
複製代碼
根據上面的代碼,即便在外部函數返回以後,內部函數(即,greetingInfo)也能夠訪問外部函數做用域(即 Welcome)中的變量。
模塊是指獨立、可重用代碼的小單元,也是許多 JavaScript 設計模式的基礎。大多數 JavaScript 模塊導出對象字面量、函數或構造函數
如下是在 javascript 生態系統中使用模塊的好處
做用域是在運行時代碼的某些特定部分中變量、函數和對象的可訪問性。換句話說,範圍決定了代碼區域中變量和其餘資源的可見性。
Service Worker 基本上是一個在後臺運行的腳本(JavaScript 文件),與網頁分離並提供不須要網頁或用戶交互的功能。Service Worker 的一些主要功能是豐富的離線體驗(離線第一個 Web 應用程序開發)、按期後臺同步、推送通知、攔截和處理網絡請求以及以編程方式管理響應緩存。
Service Worker 不能直接訪問 DOM。可是它能夠經過響應經過postMessage
接口發送的消息與它控制的頁面進行通訊,而且這些頁面能夠操做 DOM。
Service Worker 的問題在於它在不使用時會被終止,並在下次須要時從新啓動,所以您不能依賴 Service Worker onfetch
和onmessage
處理程序中的全局狀態。在這種狀況下,服務工做者將有權訪問 IndexedDB API,以便在從新啓動時保持和重用。
IndexedDB 是用於客戶端存儲大量結構化數據(包括文件/blob)的低級 API。此 API 使用索引來啓用此數據的高性能搜索。
Web 存儲是一種 API,它提供了一種機制,瀏覽器能夠經過該機制以比使用 cookie 更直觀的方式在用戶瀏覽器中本地存儲鍵/值對。Web 存儲提供了兩種在客戶端存儲數據的機制。
post message是一種啓用 Window 對象之間的跨源通訊的方法。(即,在頁面和它產生的彈出窗口之間,或在頁面和嵌入其中的 iframe 之間)。一般,當且僅當頁面遵循同源策略(即頁面共享相同的協議、端口號和主機)時,容許不一樣頁面上的腳本相互訪問。
你能夠在這篇文章中更詳細地瞭解Cookie :
haiyong.blog.csdn.net/article/det…
cookie 是存儲在您的計算機上以供瀏覽器訪問的一段數據。Cookie 保存爲鍵/值對。
例如,您能夠建立一個名爲 username 的 cookie,以下所示,
document.cookie = "username=Haiyong";
複製代碼
Cookie 用於記住有關用戶我的資料的信息(例如用戶名)。它基本上包括兩個步驟,
如下選項可用於 cookie,
默認狀況下,cookie 會在瀏覽器關閉時被刪除,但您能夠經過設置到期日期(UTC 時間)來更改此行爲。
document.cookie = "username=Haiyong; expires=Sat, 8 Jun 2019 12:00:00 UTC";
複製代碼
默認狀況下,cookie 屬於當前頁面。可是您可使用路徑參數告訴瀏覽器 cookie 所屬的路徑。
document.cookie = "username=Haiyong; path=/services";
複製代碼
document.cookie = "username=; expires=Fri, 07 Jun 2019 00:00:00 UTC; path=/;";
複製代碼
注意:您應該定義 cookie 路徑選項以確保您刪除正確的 cookie。除非您指定路徑參數,不然某些瀏覽器不容許刪除 cookie。
如下是 cookie、本地存儲和會話存儲之間的一些區別,
特徵 | cookie | 本地存儲 | 會話存儲 |
---|---|---|---|
在客戶端或服務器端訪問 | 服務器端和客戶端 | 僅客戶端 | 僅客戶端 |
Lifetime | 使用 Expires 選項配置 | 直到刪除 | 直到選項卡關閉 |
SSL | 支持 | 支持的 | 不支持 |
最大數據大小 | 4KB | 5 MB | 5MB |
⬆ 返回頂部 |
LocalStorage 與 SessionStorage 相同,但即便瀏覽器關閉並從新打開(即它沒有過時時間),它也會保留數據,而在 sessionStorage 中,當頁面會話結束時,數據會被清除。
Window 對象實現了WindowLocalStorage
和WindowSessionStorage
對象,它們分別具備localStorage
(window.localStorage) 和sessionStorage
(window.sessionStorage) 屬性。這些屬性建立 Storage 對象的實例,經過該實例能夠爲特定域和存儲類型(會話或本地)設置、檢索和刪除數據項。 例如,您能夠讀寫本地存儲對象,以下所示
localStorage.setItem('logo', document.getElementById('logo').value);
localStorage.getItem('logo');
複製代碼
會話存儲提供了讀取、寫入和清除會話數據的方法
// 將數據保存到 sessionStorage
sessionStorage.setItem('key', 'value');
// 從 sessionStorage 獲取保存的數據
let data = sessionStorage.getItem('key');
// 從 sessionStorage 中刪除保存的數據
sessionStorage.removeItem('key');
// 從 sessionStorage 中刪除全部保存的數據
sessionStorage.clear();
複製代碼
StorageEvent 是在另外一個文檔的上下文中更改存儲區域時觸發的事件。而 onstorage 屬性是一個用於處理存儲事件的 EventHandler。 語法以下
window.onstorage = functionRef;
複製代碼
讓咱們以記錄存儲鍵及其值的 onstorage 事件處理程序的示例用法爲例
window.onstorage = function(e) {
console.log('The ' + e.key +
' key has been changed from ' + e.oldValue +
' to ' + e.newValue + '.');
};
複製代碼
Web存儲更安全,能夠在本地存儲大量數據,不影響網站性能。此外,信息永遠不會傳輸到服務器。所以,這是比 Cookie 更推薦的方法。
在使用網絡存儲以前,您須要檢查瀏覽器對 localStorage 和 sessionStorage 的支持,
if (typeof(Storage) !== "undefined") {
// localStorage/sessionStorage 的代碼。
} else {
// 對不起! 沒有網絡存儲支持..
}
複製代碼
在使用以前,您須要檢查瀏覽器對 Web Worker 的支持
if (typeof(Worker) !== "undefined") {
// Web worker支持的代碼。
} else {
// 對不起! 沒有 Web Worker 支持.
}
複製代碼
您須要按照如下步驟開始使用網絡工做者進行計數示例
建立 Web Worker 文件:您須要編寫一個腳原本增長計數值。咱們將其命名爲 counter.js
let i = 0;
function timedCount() {
i = i + 1;
postMessage(i);
setTimeout("timedCount()",500);
}
timedCount();
複製代碼
這裏使用 postMessage() 方法將消息回傳到 HTML 頁面
建立 Web Worker 對象:您能夠經過檢查瀏覽器支持來建立 Web Worker 對象。讓咱們將此文件命名爲 web_worker_example.js
if (typeof(w) == "undefined") {
w = new Worker("counter.js");
}
複製代碼
咱們能夠接收來自網絡工做者的消息
w.onmessage = function(event){
document.getElementById("message").innerHTML = event.data;
};
複製代碼
終止 Web Worker:Web Worker 將繼續偵聽消息(即便在外部腳本完成後),直到它被終止。您可使用 terminate() 方法終止對消息的偵聽。
w.terminate();
複製代碼
重用 Web Worker:若是將 worker 變量設置爲 undefined,則能夠重用代碼
w = undefined;
複製代碼
WebWorker 無權訪問如下 javascript 對象,由於它們是在外部文件中定義的
promise是一個對象,它可能會在將來的某個時間產生一個單一的值,其中有一個已解決的值或一個未解決的緣由(例如,網絡錯誤)。它將處於 3 種可能狀態之一:已完成、已拒絕或未決。
Promise 建立的語法以下所示,
const promise = new Promise(function(resolve, reject) {
// promise description
})
複製代碼
承諾的用法以下,
const promise = new Promise(resolve => {
setTimeout(() => {
resolve("I'm a Promise!");
}, 5000);
}, reject => {
});
promise.then(value => console.log(value));
複製代碼
Promise 用於處理異步操做。它們經過減小回調地獄和編寫更乾淨的代碼爲回調提供了一種替代方法。
Promise 具備三種狀態:
回調函數是做爲參數傳遞給另外一個函數的函數。這個函數在外部函數內部調用以完成一個動做。
咱們舉一個簡單的例子來講明如何使用回調函數
function callbackFunction(name) {
console.log('Hello ' + name);
}
function outerFunction(callback) {
let name = prompt('Please enter your name.');
callback(name);
}
outerFunction(callbackFunction);
複製代碼
回調是必需的,由於 javascript 是一種事件驅動的語言。這意味着 javascript 將在偵聽其餘事件的同時繼續執行,而不是等待響應。 讓咱們舉一個例子,第一個函數調用 API 調用(由 setTimeout 模擬)和下一個函數記錄消息。
function firstFunction(){
// 模擬代碼延遲
setTimeout( function(){
console.log('First function called');
}, 1000 );
}
function secondFunction(){
console.log('Second function called');
}
firstFunction();
secondFunction();
Output
// Second function called
// First function called
複製代碼
從輸出中能夠看出,javascript 沒有等待第一個函數的響應,而且執行了剩餘的代碼塊。所以,回調用於確保某些代碼在其餘代碼完成執行以前不會執行。
回調地獄是一種具備多個嵌套回調的反模式,這使得在處理異步邏輯時代碼難以閱讀和調試。回調地獄看起來像下面,
async1(function(){
async2(function(){
async3(function(){
async4(function(){
....
});
});
});
});
複製代碼
服務器發送事件 (SSE) 是一種服務器推送技術,使瀏覽器可以經過 HTTP 鏈接從服務器接收自動更新,而無需求助於輪詢。這些是一種單向通訊通道 - 事件僅從服務器流向客戶端。這已用於CSDN博客更新、股票價格更新、新聞提要等。
EventSource 對象用於接收服務器發送的事件通知。例如,您能夠從服務器接收消息,以下所示,
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("sse_generator.js");
source.onmessage = function(event) {
document.getElementById("output").innerHTML += event.data + "<br>";
};
}
複製代碼
您能夠在使用以前對服務器發送的事件執行瀏覽器支持,以下所示,
if(typeof(EventSource) !== "undefined") {
// 支持服務器發送的事件。 讓咱們在這裏有一些代碼!
} else {
// 不支持服務器發送的事件
}
複製代碼
如下是可用於服務器發送事件的事件列表
活動 | 說明 |
---|---|
打開 | 它在打開與服務器的鏈接時使用 |
留言 | 收到消息時使用此事件 |
錯誤 | 發生錯誤時發生 |
promise必須遵循一組特定的規則,
您能夠將一個回調嵌套在另外一個回調中,以依次執行操做。這被稱爲回調中的回調。
loadScript('/script1.js', function(script) {
console.log('first script is loaded');
loadScript('/script2.js', function(script) {
console.log('second script is loaded');
loadScript('/script3.js', function(script) {
console.log('third script is loaded');
// 加載全部腳本後
});
})
});
複製代碼
使用 Promise 一個接一個地執行一系列異步任務的過程稱爲 Promise chaining。讓咱們舉一個計算最終結果的promise chaining的例子,
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000);
}).then(function(result) {
console.log(result); // 1
return result * 2;
}).then(function(result) {
console.log(result); // 2
return result * 3;
}).then(function(result) {
console.log(result); // 6
return result * 4;
});
複製代碼
在上述處理程序中,結果經過如下工做流程傳遞給 .then() 處理程序鏈,
1.最初的promise 在 1 秒內解決, 2.在.then經過記錄 result(1) 調用該處理程序以後,而後返回一個值爲 result * 2 的承諾。 3.以後,.then經過記錄 result(2)將值傳遞給下一個處理程序,並返回一個結果爲 * 3 的承諾。 4.最後.then經過記錄 result(6)傳遞給最後一個處理程序的值並返回一個結果爲 * 4 的承諾。
Promise.all 是一個將一系列承諾做爲輸入(可迭代)的承諾,當全部承諾都獲得解決或其中任何一個被拒絕時,它就會獲得解決。例如,promise.all 方法的語法以下,
Promise.all([Promise1, Promise2, Promise3]) .then(result) => { console.log(result) }) .catch(error => console.log(`Error in promises ${error}`))
複製代碼
==注意==:請記住,承諾的順序(輸出結果)按照輸入順序進行維護。
Promise.race() 方法將返回首先解決或拒絕的承諾實例。讓咱們舉一個race()方法的例子,其中promise2首先被解析
var promise1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 500, 'one');
});
var promise2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'two');
});
Promise.race([promise1, promise2]).then(function(value) {
console.log(value); // "two" // 兩個 promise 都會解決,但 promise2 更快
});
複製代碼
嚴格模式是 ECMAScript 5 中的一項新功能,它容許您將程序或函數置於「嚴格」操做上下文中。經過這種方式,它能夠防止執行某些操做並引起更多異常。文字表達式"use strict
";指示瀏覽器在嚴格模式下使用 javascript 代碼。
經過將「錯誤語法」通知爲實際錯誤,嚴格模式對於編寫「安全」JavaScript 頗有用。例如,它消除了經過拋出錯誤而意外建立全局變量的狀況,而且還會在分配給不可寫屬性、getter-only 屬性、不存在的屬性、不存在的變量或不存在的變量時引起錯誤。現有的對象。
嚴格模式是經過添加「use strict」來聲明的;到腳本或函數的開頭。 若是在腳本的開頭聲明,則它具備全局做用域。
"use strict";
x = 3.14; // 這將致使錯誤,由於 x 未聲明
複製代碼
若是你在函數內部聲明,它具備局部做用域
x = 3.14; // 這不會致使錯誤。
myFunction();
function myFunction() {
"use strict";
y = 3.14; // This will cause an error
}
複製代碼
雙感嘆號或否認 (!!) 確保結果類型是布爾值。若是它是假的(例如 0、空、未定義等),它將是假的,不然爲真。
例如,您可使用如下表達式測試 IE 版本,
let isIE8 = false;
isIE8 = !! navigator.userAgent.match(/MSIE 8.0/);
console.log(isIE8); // returns true or false
複製代碼
若是您不使用此表達式,則它返回原始值。
console.log(navigator.userAgent.match(/MSIE 8.0/)); // 返回一個數組或 null
複製代碼
delete 關鍵字用於刪除屬性及其值。
var user= {name: "Haiyong", age:20};
delete user.age;
console.log(user); // {name: "Haiyong"}
複製代碼
您可使用 JavaScript typeof 運算符來查找 JavaScript 變量的類型。它返回變量或表達式的類型。
typeof "Haiyong Abraham" // Returns "string"
typeof (1 + 2) // Returns "number"
複製代碼
undefined 屬性表示一個變量沒有被賦值,或者根本沒有聲明。未定義值的類型也是未定義的。
var user; // 值未定義,類型未定義
console.log(typeof(user)) //未定義
複製代碼
任何變量均可以經過將值設置爲 undefined 來清空。
user = undefined
複製代碼
值 null 表示有意缺乏任何對象值。它是 JavaScript 的原始值之一。空值的類型是對象。 您能夠經過將值設置爲 null 來清空變量。
var user = null;
console.log(typeof(user)) //object
複製代碼
如下是 null 和 undefined 之間的主要區別,
null | undefined |
---|---|
它是一個賦值值,表示變量不指向任何對象。 | 它不是已聲明變量但還沒有賦值的賦值值。 |
null 的類型是object | undefined 的類型是 undefined |
空值是一個原始值,表示空、空或不存在的引用。 | 未定義值是在變量還沒有賦值時使用的原始值。 |
表示變量沒有值 | 表示沒有變量自己 |
執行原始操做時轉換爲零 (0) | 執行原始操做時轉換爲 NaN |
eval() 函數計算表示爲字符串的 JavaScript 代碼。字符串能夠是 JavaScript 表達式、變量、語句或語句序列。
console.log(eval('1 + 2')); // 3
複製代碼
如下是Window和Document之間的主要區別,
Window | Document |
---|---|
它是任何網頁中的根級元素 | 它是 window 對象的直接子級。這也稱爲文檔對象模型(DOM) |
默認狀況下,窗口對象在頁面中隱式可用 | 您能夠經過 window.document 或 document 訪問它。 |
它有alert()、confirm()等方法和文檔、位置等屬性 | 它提供了 getElementById、getElementByTagName、createElement 等方法 |
window.history 對象包含瀏覽器的歷史記錄。您可使用 back() 和 next() 方法加載歷史記錄中的上一個和下一個 URL。
function goBack() {
window.history.back()
}
function goForward() {
window.history.forward()
}
複製代碼
==注意==:您也能夠在沒有窗口前綴的狀況下訪問歷史記錄。
所述mouseEvent getModifierState()
用於返回一個布爾值,指示指定的修飾鍵是否被激活。CapsLock、ScrollLock 和 NumLock 等修飾符在單擊時激活,再次單擊時停用。
讓咱們以一個輸入元素爲例來檢測 CapsLock 開/關行爲,
<input type="password" onmousedown="enterInput(event)">
<p id="feedback"></p>
<script> function enterInput(e) { var flag = e.getModifierState("CapsLock"); if(flag) { document.getElementById("feedback").innerHTML = "CapsLock activated"; } else { document.getElementById("feedback").innerHTML = "CapsLock not activated"; } } </script>
複製代碼
isNaN() 函數用於肯定一個值是否爲非法數字(Not-a-Number)。即,若是該值等於 NaN,則此函數返回 true。不然返回false。
isNaN('Hello') //true
isNaN('100') //false
複製代碼
如下是未聲明和未定義變量之間的主要區別,
undeclared | undefined |
---|---|
這些變量不存在於程序中且未聲明 | 這些在程序中聲明但沒有賦值的變量 |
若是您嘗試讀取未聲明變量的值,則會遇到運行時錯誤 | 若是您嘗試讀取未定義變量的值,則會返回未定義值。 |
⬆ 返回頂部 | |
回到第50題 |
全局變量是那些在整個代碼長度內均可用的變量,沒有任何做用域。var 關鍵字用於聲明局部變量,但若是省略它,它將成爲全局變量
msg = "Hello" // var 缺失,它成爲全局變量
複製代碼
全局變量的問題是局部做用域和全局做用域的變量名衝突。調試和測試依賴全局變量的代碼也很困難。
NaN 屬性是一個全局屬性,表示「非數字」值。即,它表示一個值不是一個合法的數字。在程序中不多使用 NaN,但在少數狀況下能夠用做返回值
Math.sqrt(-1)
parseInt("Hello")
複製代碼
isFinite() 函數用於肯定一個數是不是一個有限的合法數。若是值爲 +infinity、-infinity 或 NaN(非數字),則返回 false,不然返回 true。
isFinite(Infinity); // false
isFinite(NaN); // false
isFinite(-Infinity); // false
isFinite(100); // true
複製代碼
事件流是在網頁上接收事件的順序。當您單擊嵌套在各類其餘元素中的元素時,在您的單擊實際到達其目的地或目標元素以前,它必須首先觸發其每一個父元素的單擊事件,從全局窗口對象的頂部開始。
事件流有兩種方式
事件冒泡是一種事件傳播,其中事件首先在最內層的目標元素上觸發,而後在同一嵌套層次結構中的目標元素的祖先(父級)上依次觸發,直到到達最外層的 DOM 元素。
事件捕獲是一種事件傳播,其中事件首先被最外層元素捕獲,而後在同一嵌套層次結構中的目標元素的後代(子級)上連續觸發,直到它到達最內層 DOM 元素。
您可使用 JavaScript 提交表單,使用 document.form[0].submit()。使用 onsubmit 事件處理程序提交全部表單輸入的信息
function submit() {
document.form[0].submit();
}
複製代碼
window.navigator 對象包含有關訪問者瀏覽器操做系統詳細信息的信息。一些操做系統屬性在平臺屬性下可用,
console.log(navigator.platform);
複製代碼
DOMContentLoaded當初始 HTML 文檔徹底加載並解析完畢,無需等待資產(樣式表、圖像和子框架)完成加載時,將觸發該事件。而當整個頁面加載時會觸發 load 事件,包括全部依賴資源(樣式表、圖像)。
Native objects
是 ECMAScript 規範定義的 JavaScript 語言的一部分的對象。例如,ECMAScript 規範中定義的 String、Math、RegExp、Object、Function 等核心對象。Host objects
是瀏覽器或運行時環境(節點)提供的對象。例如,窗口、XmlHttpRequest、DOM節點等被視爲宿主對象。User objects
是在 javascript 代碼中定義的對象。例如,爲配置文件信息建立的用戶對象。您可使用如下工具或技術來調試 javascript
優勢:
1.它避免了不可讀的回調地獄 2.使用 .then() 輕鬆編寫順序異步代碼 3.使用 Promise.all() 輕鬆編寫並行異步代碼 4.解決回調的一些常見問題(回調太晚、太早、屢次和吞下錯誤/異常)
缺點:
1.它編寫了少許的複雜代碼 2.若是不支持 ES6,你須要加載一個 polyfill
Attributes 在 HTML 標記上定義,而properties 在 DOM 上定義。例如,下面的 HTML 元素有兩個attributes 類型和值,
<input type="text" value="Name:">
複製代碼
您能夠檢索attribute 值以下,
const input = document.querySelector('input');
console.log(input.getAttribute('value')); // Good morning
console.log(input.value); // Good morning
複製代碼
將文本字段的值更改成「Good evening」後,它變得像
console.log(input.getAttribute('value')); // Good morning
console.log(input.value); // Good evening
複製代碼
同源策略是一種防止 JavaScript 跨域邊界發出請求的策略。源定義爲 URI 方案、主機名和端口號的組合。若是啓用此策略,則它會阻止一個頁面上的惡意腳本使用文檔對象模型 (DOM) 獲取對另外一個網頁上的敏感數據的訪問權限。
void(0) 用於防止頁面刷新。這將有助於消除不須要的反作用,由於它將返回未定義的原始值。它一般用於使用 href="JavaScript:Void(0);"
的 HTML 文檔。 一個元素內。 即,當您單擊連接時,瀏覽器會加載一個新頁面或刷新同一頁面。 可是使用此表達式將阻止這種行爲。
例如,下面的連接在不從新加載頁面的狀況下通知消息
<a href="JavaScript:void(0);" onclick="alert('Well done!')">Click Me!</a>
複製代碼
JavaScript 是一種解釋型語言,而不是一種編譯型語言。瀏覽器中的解釋器讀取 JavaScript 代碼,解釋每一行,而後運行它。現在,現代瀏覽器使用一種稱爲即時 (JIT) 編譯的技術,該技術在 JavaScript 即將運行時將其編譯爲可執行的字節碼。
是的,JavaScript 是一種區分大小寫的語言。語言關鍵字、變量、函數和對象名稱以及任何其餘標識符必須始終使用一致的大寫字母輸入。
不,它們徹底是兩種不一樣的編程語言,彼此沒有任何關係。可是它們都是面向對象的編程語言,而且像許多其餘語言同樣,它們的基本功能(if、else、for、switch、break、continue 等)遵循相似的語法。
具體區別能夠查看我這篇文章:
haiyong.blog.csdn.net/article/det…
event是發生在 HTML 元素上的「事物」。在 HTML 頁面中使用 JavaScript 時,JavaScript 能夠react處理這些事件。HTML 事件的一些示例是,
讓咱們描述一下按鈕元素的點擊事件的行爲,
<!doctype html>
<html>
<head>
<script> function greeting() { alert('Hello! Good morning'); } </script>
</head>
<body>
<button type="button" onclick="greeting()">Click me</button>
</body>
</html>
複製代碼
我已經寫了很長一段時間的技術博客,而且主要經過CSDN發表,這是個人一篇面試題文章。但願大家會喜歡!
若是你真的從這篇文章中學到了一些新東西,喜歡它,收藏它並與你的小夥伴分享。🤗最後,不要忘了❤或📑支持一下哦