最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript核心難點(diǎn)之變量提升、作用域、Promise、this與類型轉(zhuǎn)換解析

 更新時(shí)間:2026年05月28日 09:05:19   作者:We?ct  
在前端開發(fā)領(lǐng)域JavaScript作為基石語言,其核心概念的掌握程度直接決定了面試成敗,這篇文章主要介紹了JavaScript核心難點(diǎn)之變量提升、作用域、Promise、this與類型轉(zhuǎn)換的相關(guān)資料,需要的朋友可以參考下

前言

在前端開發(fā)中,JavaScript的變量提升、作用域、Promise異步、this指向以及隱式類型轉(zhuǎn)換,是高頻面試考點(diǎn),也是實(shí)際開發(fā)中容易踩坑的核心知識(shí)點(diǎn)。很多開發(fā)者在入門時(shí)會(huì)被這些概念繞暈,本文將用“通俗類比+專業(yè)拆解”的方式,結(jié)合具體代碼案例,把每個(gè)難點(diǎn)講透,幫你徹底理清邏輯、避開陷阱。

一、變量提升:var的“穿透性”與函數(shù)提升的特殊規(guī)則

變量提升(Hoisting)是JS引擎在代碼執(zhí)行前的“預(yù)編譯”行為——簡(jiǎn)單說,就是JS會(huì)把變量和函數(shù)的聲明“提前”到當(dāng)前作用域的頂部,但賦值不會(huì)提升。這里重點(diǎn)區(qū)分var變量提升和函數(shù)提升的差異,尤其是if塊內(nèi)的函數(shù)提升,是高頻易錯(cuò)點(diǎn)。

1.1 核心規(guī)則:var沒有塊級(jí)作用域,會(huì)“穿透”所有塊

在ES6之前,JS中只有“函數(shù)作用域”和“全局作用域”,沒有“塊級(jí)作用域”——也就是說,if(){}、for(){}、while(){}、單獨(dú){}這些代碼塊,根本“關(guān)不住”var聲明的變量。var聲明的變量會(huì)穿透這些塊,提升到最近的函數(shù)頂部(如果在函數(shù)內(nèi))或全局頂部(如果在函數(shù)外)。

舉個(gè)通俗的例子:var就像一個(gè)“不受約束的調(diào)皮蛋”,不管你把它放在哪個(gè)小房間(代碼塊)里,它都會(huì)偷偷跑到房間的最外層(最近函數(shù)/全局),提前“占位置”。

1.2 易錯(cuò)點(diǎn):if內(nèi)的函數(shù)提升(關(guān)鍵案例解析)

函數(shù)提升分兩種情況:普通函數(shù)聲明(function fn(){})會(huì)提升,而立即執(zhí)行函數(shù)((function(){})())本身不會(huì)提升。其中,if塊內(nèi)的函數(shù)提升最為特殊,瀏覽器會(huì)做特殊處理,我們結(jié)合具體案例看:

var a = 0;
console.log("第一次輸出a: ", a); // 輸出0
if (true) {
  a = 1;
  console.log("第二次輸出a: ", a); // 輸出1
  function a() {} // 函數(shù)聲明,會(huì)觸發(fā)特殊提升
  a = 2;
  console.log("第三次輸出a: ", a); // 輸出2
}
console.log("第四次輸出a: ", a); // 輸出1

很多人會(huì)疑惑:第四次輸出為什么是1?不是應(yīng)該是2嗎?這里瀏覽器的執(zhí)行邏輯分3步,順序至關(guān)重要(記牢這3步,避免踩坑):

  1. 先把【當(dāng)前塊內(nèi)a的值】同步給外部a(此時(shí)塊內(nèi)a已經(jīng)被賦值為1)→ 外部a從0變成1;

  2. 再把函數(shù)a賦值給塊內(nèi)a → 塊內(nèi)a從1變成函數(shù)a;

  3. 最后立刻斷開塊內(nèi)a和外部a的關(guān)聯(lián) → 后續(xù)塊內(nèi)a賦值為2,不會(huì)影響外部a。

簡(jiǎn)單總結(jié):if塊內(nèi)的函數(shù)聲明,會(huì)先同步塊內(nèi)變量值到外部,再賦值函數(shù),最后斷開關(guān)聯(lián),這是瀏覽器的特殊處理邏輯,也是面試常考的“坑點(diǎn)”。

1.3 延伸案例:var聲明的“全局污染”陷阱

(function(){
   var x = y = 1; // 關(guān)鍵:y沒有var聲明
})();
var z;

console.log(y);  // 輸出1
console.log(z);  // 輸出undefined
console.log(x);  // 報(bào)錯(cuò):Uncaught ReferenceError: x is not defined

解析(通俗版):var x = y = 1; 等價(jià)于 y = 1; var x = y; —— y沒有var聲明,會(huì)自動(dòng)變成全局變量(相當(dāng)于window.y = 1),而x有var聲明,是函數(shù)內(nèi)的局部變量,函數(shù)執(zhí)行完后銷毀,所以外部訪問不到x。

專業(yè)重點(diǎn):沒有var/let/const聲明的變量,會(huì)自動(dòng)掛載到全局對(duì)象(window)上,造成全局污染,這是開發(fā)中要堅(jiān)決避免的寫法。

1.4 再練一個(gè):函數(shù)內(nèi)var提升的“undefined陷阱”

var friendName = 'World';
(function() {
  if (typeof friendName === 'undefined') {
    var friendName = 'Jack';
    console.log('Goodbye ' + friendName); // 輸出Goodbye Jack
  } else {
    console.log('Hello ' + friendName);
  }
})();

解析:函數(shù)內(nèi)的var friendName會(huì)提升到函數(shù)頂部,相當(dāng)于“var friendName;”(只聲明,未賦值),所以typeof friendName === 'undefined’為true,進(jìn)入if塊賦值為Jack并輸出。這里的關(guān)鍵是:函數(shù)內(nèi)的var提升,會(huì)覆蓋外部的全局變量(作用域優(yōu)先級(jí):局部>全局)。

二、作用域與作用域鏈:函數(shù)“出生地”決定能訪問哪些變量

作用域的核心:函數(shù)能訪問哪些變量,取決于它的“定義時(shí)”的作用域,而不是“調(diào)用時(shí)”的作用域。作用域鏈就是函數(shù)定義時(shí)形成的“變量查找鏈條”,從自身作用域開始,逐級(jí)向上查找,直到全局作用域。

通俗類比:作用域就像“你出生的家庭”,你能拿到家里的東西(變量),取決于你出生在哪個(gè)家(定義時(shí)的作用域),而不是你后來去了哪個(gè)家(調(diào)用時(shí)的作用域)。

2.1 基礎(chǔ)案例:函數(shù)定義在內(nèi)部,能訪問外部變量

function a() {
    var temp = 10;
    function b() {
        console.log(temp); // 輸出10
    }
    b();
}
a();

解析:函數(shù)b定義在函數(shù)a內(nèi)部,所以b的作用域鏈包含a的作用域和全局作用域,能訪問到a內(nèi)的temp變量。

2.2 反例:函數(shù)定義在全局,訪問不到局部變量

function a() {
    var temp = 10;
    b(); // 調(diào)用全局的b
}
function b() {
    console.log(temp); // 報(bào)錯(cuò):temp is not defined
}
a();

解析:函數(shù)b定義在全局作用域,它的作用域鏈只有全局作用域,找不到a內(nèi)的局部變量temp,所以報(bào)錯(cuò)。這就是“定義時(shí)決定作用域”的核心體現(xiàn)。

2.3 進(jìn)階:閉包與作用域的結(jié)合(高頻面試題)

閉包的本質(zhì):函數(shù)嵌套函數(shù),內(nèi)部函數(shù)引用外部函數(shù)的變量,外部函數(shù)執(zhí)行后,內(nèi)部函數(shù)依然能訪問到外部函數(shù)的變量(因?yàn)殚]包保存了外部函數(shù)的作用域)。每次調(diào)用外部函數(shù),都會(huì)生成一個(gè)新的閉包環(huán)境,互不影響。

function fun(n, o) {
  console.log(o)
  return {
    fun: function(m){
      return fun(m, n); // 內(nèi)部函數(shù)引用外部函數(shù)的n,形成閉包
    }
  };
}
// 三個(gè)案例,重點(diǎn)區(qū)分閉包環(huán)境
var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3); // 輸出:undefined、0、0、0
var b = fun(0).fun(1).fun(2).fun(3); // 輸出:undefined、0、1、2
var c = fun(0).fun(1);  c.fun(2);  c.fun(3); // 輸出:undefined、0、1、1

解析(通俗版):

  • var a = fun(0):調(diào)用fun(0),o是undefined,返回一個(gè)對(duì)象,這個(gè)對(duì)象的fun方法引用了外部fun的n=0(閉包保存n=0),所以后續(xù)a.fun(1)、a.fun(2),都是調(diào)用fun(m, 0),o始終是0;

  • var b = fun(0).fun(1).fun(2).fun(3):每次調(diào)用fun都會(huì)生成新閉包——fun(0)返回的對(duì)象fun引用n=0,調(diào)用fun(1)時(shí),fun(1,0)返回的對(duì)象fun引用n=1,以此類推,o依次是0、1、2;

  • var c = fun(0).fun(1):fun(0)返回的對(duì)象fun引用n=0,調(diào)用fun(1)得到fun(1,0),返回的對(duì)象fun引用n=1,后續(xù)c.fun(2)、c.fun(3),都是調(diào)用fun(m,1),o始終是1。

核心記住:閉包保存的是“定義時(shí)”的作用域,每次調(diào)用外部函數(shù),都會(huì)生成新的閉包環(huán)境,變量值互不干擾。

三、Promise與異步執(zhí)行:微任務(wù)、宏任務(wù)的執(zhí)行順序

Promise是JS處理異步操作的核心,很多開發(fā)者會(huì)被它的執(zhí)行順序、狀態(tài)變化、鏈?zhǔn)秸{(diào)用繞暈。核心要點(diǎn):同步代碼先執(zhí)行,再執(zhí)行所有微任務(wù),最后執(zhí)行宏任務(wù);每執(zhí)行一個(gè)宏任務(wù)后,都會(huì)清空當(dāng)前所有微任務(wù)。

先明確兩個(gè)概念(通俗版):

  • 微任務(wù):“優(yōu)先級(jí)高”的異步任務(wù),比如Promise.then/catch/finally、async/await(本質(zhì)也是Promise)、process.nextTick(Node環(huán)境);

  • 宏任務(wù):“優(yōu)先級(jí)低”的異步任務(wù),比如setTimeout、setInterval、DOM事件、AJAX請(qǐng)求。

3.1 基礎(chǔ)案例1:Promise未resolve/reject,狀態(tài)不變

const promise = new Promise((resolve, reject) => {
  console.log(1); // 同步代碼,先執(zhí)行
  console.log(2); // 同步代碼,繼續(xù)執(zhí)行
});
promise.then(() => {
  console.log(3); // 不會(huì)執(zhí)行,因?yàn)镻romise未resolve/reject
});
console.log(4); // 同步代碼,執(zhí)行

輸出結(jié)果:1 2 4。解析:Promise構(gòu)造函數(shù)內(nèi)的代碼是同步執(zhí)行的,而then方法只有在Promise狀態(tài)變?yōu)閞esolved(成功)或rejected(失敗)時(shí)才會(huì)執(zhí)行,這里沒有調(diào)用resolve/reject,狀態(tài)一直是pending,所以then回調(diào)不執(zhí)行。

3.2 基礎(chǔ)案例2:Promise狀態(tài)變化與then回調(diào)執(zhí)行

const promise1 = new Promise((resolve, reject) => {
  console.log('promise1'); // 同步執(zhí)行
  resolve('resolve1'); // 改變狀態(tài)為resolved
})
const promise2 = promise1.then(res => {
  console.log(res); // 微任務(wù),同步代碼執(zhí)行完后執(zhí)行
})
console.log('1', promise1); // 同步執(zhí)行,promise1狀態(tài)為fulfilled
console.log('2', promise2); // 同步執(zhí)行,promise2狀態(tài)為pending

輸出結(jié)果:promise1 → 1 fulfilled resolve1 → 2 pending → resolve1。解析:promise1調(diào)用resolve后,狀態(tài)變?yōu)閒ulfilled,then回調(diào)進(jìn)入微任務(wù)隊(duì)列;同步代碼執(zhí)行完后,執(zhí)行微任務(wù),打印res的值。

3.3 進(jìn)階案例:微任務(wù)與宏任務(wù)的執(zhí)行順序(高頻面試題)

Promise.resolve().then(() => {
  console.log('promise1'); // 微任務(wù)1
  const timer2 = setTimeout(() => {
    console.log('timer2') // 宏任務(wù)2
  }, 0)
});
const timer1 = setTimeout(() => {
  console.log('timer1') // 宏任務(wù)1
  Promise.resolve().then(() => {
    console.log('promise2') // 微任務(wù)2
  })
}, 0)
console.log('start'); // 同步代碼

輸出結(jié)果:start → promise1 → timer1 → promise2 → timer2。解析步驟(記牢這個(gè)順序,搞定所有異步面試題):

  1. 執(zhí)行所有同步代碼:console.log(‘start’);

  2. 執(zhí)行所有微任務(wù):Promise.resolve().then(),打印promise1,同時(shí)創(chuàng)建宏任務(wù)timer2;

  3. 執(zhí)行宏任務(wù)隊(duì)列中的第一個(gè)宏任務(wù):timer1,打印timer1;

  4. 執(zhí)行當(dāng)前宏任務(wù)產(chǎn)生的所有微任務(wù):Promise.resolve().then(),打印promise2;

  5. 執(zhí)行下一個(gè)宏任務(wù):timer2,打印timer2。

3.4 常見陷阱:Promise.then的值穿透、return錯(cuò)誤不進(jìn)catch

陷阱1:then傳非函數(shù),發(fā)生值穿透

Promise.resolve(1)
  .then(2) // 傳數(shù)字,非函數(shù) → 值穿透
  .then(Promise.resolve(3)) // 傳Promise,非函數(shù) → 值穿透
  .then(console.log) // 傳函數(shù),打印1

解析:Promise.then()必須接收一個(gè)函數(shù)作為回調(diào),如果傳的是數(shù)字、Promise、對(duì)象等非函數(shù),會(huì)發(fā)生“值穿透”——把前一個(gè)then的有效結(jié)果,直接傳給下一個(gè)then,所以最終打印1。

陷阱2:return錯(cuò)誤對(duì)象,不會(huì)進(jìn)入catch

Promise.resolve().then(() => {
  return new Error('error!!!') // return非Promise錯(cuò)誤對(duì)象
}).then(res => {
  console.log("then: ", res) // 打印then: Error: error!!!
}).catch(err => {
  console.log("catch: ", err) // 不會(huì)執(zhí)行
})

核心原理(一句話記牢):return任意非Promise值(包括錯(cuò)誤對(duì)象),都會(huì)把這個(gè)值當(dāng)作成功結(jié)果,傳給下一個(gè)then;只有throw錯(cuò)誤,或return Promise.reject(),才會(huì)進(jìn)入catch。

3.5 補(bǔ)充:async/await的執(zhí)行邏輯(Promise的語法糖)

async/await本質(zhì)是Promise的語法糖,await會(huì)“讓出線程”,把后面的代碼包裝成微任務(wù),放到微任務(wù)隊(duì)列,等待await后面的Promise完成后執(zhí)行。注意:如果await后面的Promise永遠(yuǎn)不resolve,會(huì)永久阻塞。

async function async1() {
  console.log("async1 start"); // 同步執(zhí)行
  await async2(); // 等待async2完成,后面的代碼變成微任務(wù)
  console.log("async1 end"); // 微任務(wù),同步代碼執(zhí)行完后執(zhí)行
}
async function async2() {
  console.log("async2"); // 同步執(zhí)行
}
async1();
console.log('start');

輸出結(jié)果:async1 start → async2 → start → async1 end。解析:async1調(diào)用后,先執(zhí)行同步代碼async1 start,再執(zhí)行async2(同步),await讓出線程,執(zhí)行外部同步代碼start,最后執(zhí)行微任務(wù)async1 end。

四、this指向:誰調(diào)用,指向誰(核心規(guī)則+易錯(cuò)案例)

this指向是JS中最靈活也最易錯(cuò)的知識(shí)點(diǎn),核心規(guī)則只有一句話:誰調(diào)用函數(shù),this就指向誰;沒有調(diào)用者(獨(dú)立函數(shù)調(diào)用),this指向全局對(duì)象(window,嚴(yán)格模式下是undefined)。但有幾個(gè)特殊情況(箭頭函數(shù)、new、apply/call/bind)需要重點(diǎn)記。

4.1 基礎(chǔ)案例1:獨(dú)立函數(shù)調(diào)用,this指向window

function foo() {
  console.log( this.a );
}
function doFoo() {
  foo(); // 獨(dú)立函數(shù)調(diào)用,沒有調(diào)用者
}
var obj = {
  a: 1,
  doFoo: doFoo
};
var a = 2; // 全局變量a,掛載到window上
obj.doFoo(); // 輸出2

解析:obj.doFoo()調(diào)用doFoo,doFoo內(nèi)部調(diào)用foo()——foo是獨(dú)立調(diào)用,沒有任何前綴(比如obj.foo()),所以this指向window,window.a是2,輸出2。

4.2 特殊情況1:箭頭函數(shù)沒有自己的this,繼承外層作用域

var a = 10;
var obj = {
  a: 20,
  say: () => {
    console.log(this.a); // 輸出10
  }
}
obj.say(); 
var anotherObj = { a: 30 };
obj.say.apply(anotherObj); // 輸出10

解析:箭頭函數(shù)沒有自己的this,this繼承外層作用域(這里外層是全局作用域),所以this指向window,window.a是10;而且箭頭函數(shù)的this一旦確定,無法通過apply、call、bind修改(即使傳了參數(shù),也無效)。

4.3 特殊情況2:new調(diào)用構(gòu)造函數(shù),this指向新對(duì)象

var obj = { 
  name : 'cuggz', 
  fun : function(){ 
    console.log(this.name); 
  } 
} 
obj.fun(); // 輸出cuggz(this指向obj)
new obj.fun(); // 輸出undefined(this指向新創(chuàng)建的空對(duì)象)

解析:new關(guān)鍵字的作用是創(chuàng)建一個(gè)新對(duì)象,然后讓構(gòu)造函數(shù)的this指向這個(gè)新對(duì)象。obj.fun()是obj調(diào)用fun,this指向obj;new obj.fun()是new調(diào)用,this指向新創(chuàng)建的空對(duì)象,空對(duì)象沒有name屬性,所以輸出undefined。

4.4 易錯(cuò)案例:立即執(zhí)行函數(shù)(IIFE)的this指向

var myObject = {
    foo: "bar",
    func: function() {
        var self = this; // 保存當(dāng)前this(指向myObject)
        console.log(this.foo);  // 輸出bar(this指向myObject)
        console.log(self.foo);  // 輸出bar(self指向myObject)
        (function() {
            console.log(this.foo);  // 輸出undefined(this指向window)
            console.log(self.foo);  // 輸出bar(self指向myObject)
        }());
    }
};
myObject.func();

解析:立即執(zhí)行函數(shù)((function(){})())是獨(dú)立函數(shù)調(diào)用,沒有調(diào)用者,所以this指向window,window沒有foo屬性,輸出undefined;而self是提前保存的myObject的this,所以能訪問到foo。

4.5 進(jìn)階案例:arguments調(diào)用函數(shù),this指向arguments

var length = 10;
function fn() {
    console.log(this.length);
}
var obj = {
  length: 5,
  method: function(fn) {
    fn(); // 獨(dú)立調(diào)用,this指向window,輸出10
    arguments[0](); // arguments調(diào)用fn,this指向arguments,輸出2
  }
};
obj.method(fn, 1); //  arguments長度是2(fn和1兩個(gè)參數(shù))

解析:arguments是函數(shù)的內(nèi)置對(duì)象,保存了函數(shù)的參數(shù)。arguments0相當(dāng)于“arguments調(diào)用fn”,所以this指向arguments,arguments的length是2(傳入了fn和1兩個(gè)參數(shù)),所以輸出2。

五、隱式類型轉(zhuǎn)換:JS的“自動(dòng)轉(zhuǎn)換”陷阱(高頻面試)

JS是弱類型語言,當(dāng)不同類型的值進(jìn)行比較或運(yùn)算時(shí),會(huì)自動(dòng)進(jìn)行類型轉(zhuǎn)換(隱式轉(zhuǎn)換),這是很多bug的來源,也是面試常考的點(diǎn)。核心記?。簩?duì)象轉(zhuǎn)原始值的規(guī)則、字符串比較規(guī)則、與=的差異。

5.1 核心規(guī)則:對(duì)象轉(zhuǎn)原始值(ToPrimitive)

任何對(duì)象(包括數(shù)組、普通對(duì)象)在轉(zhuǎn)換為原始值時(shí),遵循“先valueOf()后toString()”的優(yōu)先級(jí):

  1. 調(diào)用obj.valueOf():默認(rèn)返回對(duì)象自身(除非被重寫,比如Date對(duì)象的valueOf()返回時(shí)間戳);

  2. 若valueOf()返回的還是對(duì)象,則調(diào)用obj.toString():

    • 普通對(duì)象默認(rèn)返回"[object Object]";

    • 數(shù)組的toString()返回元素拼接的字符串(如[] → “”,[1,2] → “1,2”);

    • 函數(shù)的toString()返回函數(shù)源碼字符串。

5.2 高頻面試題:6道經(jīng)典轉(zhuǎn)換案例(必掌握)

案例1:![] == 0 的結(jié)果(true)

解析步驟:

  1. ![]:邏輯非運(yùn)算,先把[]轉(zhuǎn)布爾值——任意對(duì)象/數(shù)組轉(zhuǎn)布爾值都是true,所以![] → false;

  2. false == 0:布爾值與數(shù)字比較,先把false轉(zhuǎn)數(shù)字(Number(false) → 0);

  3. 0 == 0 → true。

案例2:{} + [] 的結(jié)果(0)

解析步驟:

  1. JS引擎會(huì)把左邊的{}當(dāng)作“空代碼塊”(不是對(duì)象),直接忽略;

  2. 剩下+[]:+是一元運(yùn)算符,會(huì)把[]轉(zhuǎn)數(shù)字——先調(diào)用valueOf()返回[](對(duì)象),再調(diào)用toString()返回"“(空字符串),Number(”") → 0;

  3. 最終結(jié)果:0。

案例3:[] + {} 的結(jié)果(“[object Object]”)

解析步驟:

  1. +兩邊都是引用類型(數(shù)組、對(duì)象),優(yōu)先進(jìn)行字符串拼接;

  2. []轉(zhuǎn)字符串:toString() → “”;

  3. {}轉(zhuǎn)字符串:toString() → “[object Object]”;

  4. “” + “[object Object]” → “[object Object]”。

案例4:“a” > “b”(false)、“10” > “2”(false)

字符串比較規(guī)則(核心):從第一個(gè)字符開始,依次比較對(duì)應(yīng)位置的字符,基于Unicode編碼(編碼值小的字符更?。?,一旦比較出結(jié)果,就提前結(jié)束;如果短字符串是長字符串的前綴,則短字符串更小。

解析:

  • “a” > “b”:"a"的Unicode編碼是97,"b"是98,97<98 → false;

  • “10” > “2”:先比較第一個(gè)字符,"1"的編碼是49,"2"是50,49<50 → false(不會(huì)繼續(xù)比較第二個(gè)字符)。

案例5:Object(123)、Object(“abc”) 的返回值類型

解析:Object()是包裝對(duì)象構(gòu)造函數(shù),傳入基本類型值,會(huì)返回對(duì)應(yīng)的包裝對(duì)象:

  • Object(123) → Number包裝對(duì)象,typeof 結(jié)果是"object";

  • Object(“abc”) → String包裝對(duì)象,typeof 結(jié)果是"object"。

注意:包裝對(duì)象是對(duì)象類型,不是基本類型,所以typeof返回"object"。

案例6:let a = {}; a == true(false)、a === true(false)

解析(結(jié)合對(duì)象轉(zhuǎn)原始值規(guī)則):

  1. a == true:

    • 對(duì)象a轉(zhuǎn)原始值:valueOf()返回{}(對(duì)象),再調(diào)用toString()返回"[object Object]";

    • 布爾值true轉(zhuǎn)數(shù)字:Number(true) → 1;

    • 比較變?yōu)?quot;[object Object]" == 1:字符串轉(zhuǎn)數(shù)字,“[object Object]” → NaN,NaN == 1 → false。

  2. a === true:嚴(yán)格相等,要求類型和值都相同,a是object類型,true是boolean類型,類型不同 → false。

總結(jié):核心要點(diǎn)速記

本文梳理了JS中最核心、最易錯(cuò)的5個(gè)知識(shí)點(diǎn),每個(gè)知識(shí)點(diǎn)都結(jié)合了案例和通俗解析,方便大家理解和記憶,最后用幾句話速記核心:

  1. 變量提升:var穿透塊,函數(shù)聲明提升,立即執(zhí)行函數(shù)不提升;

  2. 作用域:函數(shù)能訪問的變量,取決于定義時(shí)的作用域,閉包保存定義時(shí)的環(huán)境;

  3. Promise:同步→微任務(wù)→宏任務(wù),每執(zhí)行一個(gè)宏任務(wù)清空微任務(wù),then傳非函數(shù)會(huì)值穿透;

  4. this指向:誰調(diào)用指向誰,箭頭函數(shù)繼承外層this,new指向新對(duì)象;

  5. 隱式轉(zhuǎn)換:對(duì)象轉(zhuǎn)原始值先valueOf后toString,字符串比較按Unicode編碼,==會(huì)自動(dòng)轉(zhuǎn)換類型,===不轉(zhuǎn)換。

到此這篇關(guān)于JavaScript核心難點(diǎn)之變量提升、作用域、Promise、this與類型轉(zhuǎn)換解析的文章就介紹到這了,更多相關(guān)JS變量提升、作用域、Promise、this與類型轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • js 實(shí)現(xiàn)省市區(qū)三級(jí)聯(lián)動(dòng)菜單效果

    js 實(shí)現(xiàn)省市區(qū)三級(jí)聯(lián)動(dòng)菜單效果

    本文主要分享了js實(shí)現(xiàn)省市區(qū)三級(jí)聯(lián)動(dòng)菜單效果的示例代碼。具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-02-02
  • JS獲取并操作iframe中元素的方法

    JS獲取并操作iframe中元素的方法

    JS獲取并操作iframe中元素的方法,需要的朋友可以參考一下
    2013-03-03
  • webpack 代碼分離優(yōu)化快速指北

    webpack 代碼分離優(yōu)化快速指北

    這篇文章主要介紹了webpack 代碼分離優(yōu)化快速指北,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-05-05
  • javascript計(jì)算漸變顏色的實(shí)例

    javascript計(jì)算漸變顏色的實(shí)例

    這篇文章主要介紹了javascript計(jì)算漸變顏色的實(shí)例的相關(guān)資料,希望通過本文能幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-09-09
  • 微信小程序?qū)W習(xí)總結(jié)(四)事件與冒泡實(shí)例分析

    微信小程序?qū)W習(xí)總結(jié)(四)事件與冒泡實(shí)例分析

    這篇文章主要介紹了微信小程序?qū)W習(xí)總結(jié)(四)事件與冒泡,結(jié)合實(shí)例形式分析了微信小程序事件、冒泡、數(shù)據(jù)獲取相關(guān)機(jī)制、原理與操作注意事項(xiàng),需要的朋友可以參考下
    2020-06-06
  • JavaScript阻止事件冒泡和默認(rèn)行為的方法舉例

    JavaScript阻止事件冒泡和默認(rèn)行為的方法舉例

    JavaScript事件的默認(rèn)行為指瀏覽器自動(dòng)執(zhí)行的操作,如鏈接跳轉(zhuǎn)或表單提交,阻止這些行為可以使用event.preventDefault()、return?false或event.returnValue屬性,event.stopPropagation()用于阻止事件傳播,不直接阻止默認(rèn)行為,需要的朋友可以參考下
    2024-10-10
  • 鴻蒙系統(tǒng)中實(shí)現(xiàn)圖片上傳功能全流程

    鴻蒙系統(tǒng)中實(shí)現(xiàn)圖片上傳功能全流程

    在鴻蒙系統(tǒng)中實(shí)現(xiàn)圖片上傳功能,整體流程可以類比為?“選快遞→填單→發(fā)貨→簽收”?的過程,下面給大家介紹鴻蒙系統(tǒng)中實(shí)現(xiàn)圖片上傳功能全流程,感興趣的朋友一起看看吧
    2025-04-04
  • 小程序?qū)崿F(xiàn)列表點(diǎn)贊功能

    小程序?qū)崿F(xiàn)列表點(diǎn)贊功能

    這篇文章主要為大家詳細(xì)介紹了小程序?qū)崿F(xiàn)列表點(diǎn)贊功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • JavaScript包裝對(duì)象使用詳解

    JavaScript包裝對(duì)象使用詳解

    javascript代碼運(yùn)行的過程中基本類型會(huì)找到對(duì)應(yīng)的包裝對(duì)象,然后包裝對(duì)象把所有的屬性和方法給了基本類型,然后包裝對(duì)象被系統(tǒng)進(jìn)行銷毀,所以理解了包裝對(duì)象可以很好的理解之前寫的代碼為什么可以這樣做了。
    2015-07-07
  • 使用firebug進(jìn)行調(diào)試javascript的示例

    使用firebug進(jìn)行調(diào)試javascript的示例

    調(diào)試javascript的方法有很多,在本文為大家介紹下使用firebug是如何做到的,感興趣的朋友可以參考下
    2013-12-12

最新評(píng)論

西畴县| 易门县| 石棉县| 景德镇市| 平遥县| 百色市| 张家港市| 济南市| 怀仁县| 出国| 中山市| 淳化县| 中山市| 鹤山市| 西乌珠穆沁旗| 屏东县| 志丹县| 平泉县| 桃江县| 浦县| 景宁| 台山市| 兴山县| 湾仔区| 商河县| 清河县| 安吉县| 穆棱市| 榆社县| 绵竹市| 青海省| 福泉市| 黄冈市| 南平市| 杭锦旗| 青铜峡市| 西安市| 双桥区| 桦川县| 绥德县| 保德县|