摘要:真正的理解閉包的原理與使用更加透徹綁定的四種規(guī)則機(jī)制你不知道的人稱小黃書,第一次看到這本書名就想到了一句話你懂得,翻閱后感覺到很驚艷,分析的很透徹,學(xué)習(xí)起來也很快,塊級(jí)作用域語句語句相當(dāng)于比較麻煩而且用在對(duì)象上創(chuàng)建的塊作用域僅僅在聲明中有效
真正的理解閉包的原理與使用 更加透徹this綁定的四種規(guī)則機(jī)制塊級(jí)作用域
你不知道的JavaScript 人稱小黃書,第一次看到這本書名 就想到了一句話 “You konw nothing! Jon snow”(你懂得), 翻閱后感覺到很驚艷,分析的很透徹,學(xué)習(xí)起來也很快,Have fun!
if語句
for語句
with
with(obj) { a = 1; b = 2; c = 3; }
相當(dāng)于
obj.a = 1;
obj.b = 2;
obj.c = 3; (比較麻煩)
而且用with在對(duì)象上創(chuàng)建的塊作用域僅僅在with聲明中有效
try / catch
catch 事實(shí)上也會(huì)創(chuàng)建一個(gè)塊作用域,且僅僅在catch內(nèi)部有效
let
const
塊作用域的用處垃圾回收
let循環(huán)
聲明提升a = 2;
var a;
console.log(a); // 2
這就是聲明提升,先有蛋(聲明),后有雞(賦值)只有聲明被提升,賦值或其他邏輯保留在原地
真正的順序是
var a (未執(zhí)行前,在編譯階段)
a = 2 (等待執(zhí)行)
console.log(a)
函數(shù)聲明會(huì)被提升,而函數(shù)表達(dá)式不會(huì)
函數(shù)聲明,變量聲明同時(shí)出現(xiàn)(一般不會(huì)出現(xiàn),出現(xiàn)情況是重復(fù)聲明), 則是 函數(shù)優(yōu)先作用域閉包
閉包實(shí)質(zhì): 當(dāng)函數(shù)可以記住并訪問所在的詞法作用域時(shí),就產(chǎn)生了閉包,即使函數(shù)在當(dāng)前詞法作用域之外執(zhí)行
將內(nèi)部函數(shù)傳遞到詞法作用域外,他都會(huì)有對(duì)原始定義作用域的引用,無論在何處執(zhí)行這個(gè)函數(shù)都會(huì)使用閉包
在定時(shí)器,時(shí)間監(jiān)聽器,Ajax請(qǐng)求,跨窗口通信,web workers 或者其他任何異步任務(wù),只要使用了
回調(diào)函數(shù),實(shí)際上都是在使用到了閉包
IIFE:立即執(zhí)行函數(shù),典型的閉包例子,IIFE會(huì)通過聲明并立即執(zhí)行函數(shù)創(chuàng)建作用域
經(jīng)典栗子
for(var i = 0; i < 5; i++) { setTimeout(function() { console.log(i) },0); } // output: 5 5 5 5 5 // setTimeoiut延遲函數(shù)會(huì)在循環(huán)結(jié)束之后執(zhí)行 ,而此時(shí)i為5 結(jié)果自然為5個(gè)5 //利用閉包解決,創(chuàng)建一個(gè)塊作用域保存一個(gè)i的副本即可 @方法1 for(var i = 0; i < 5; i++) { (function() { var j = i; setTimeout(function() { console.log(j); },0); })(); } // output: 0 1 2 3 4 @方法2 for(var i = 0; i < 5; i++) { (function(j) { setTimeout(function() { console.log(j); },0); })(i); } // output: 0 1 2 3 4 @方法3 (let即可,簡單實(shí)用) for(let i = 0; i < 5; i++) { setTimeout(function() { console.log(i) },0); } // output: 0 1 2 3 4模塊機(jī)制
關(guān)于This現(xiàn)代模塊
var MyModules = (function manager() { var modules = {}; function define(name, deps, imp) { //... modules[name] = imp.apply(imp, deps); }; function get(name) { return modules[name]; }; return { define: define, get: get }; })();未來模塊機(jī)制
bar.js function add(a, b){ return a + b; } export add; foo.js import bar from "bar" console.log(bar.add());特征
為創(chuàng)建一個(gè)內(nèi)部作用域而調(diào)用一個(gè)包裝的函數(shù)
包裝函數(shù)的返回值必須至少包含一個(gè)內(nèi)部函數(shù)的引用, 這才會(huì)創(chuàng)建涵蓋整個(gè)包裝函數(shù)內(nèi)部作用域的閉包
為什么要用 this? 1. this提供了一種更加優(yōu)雅的方式來隱式傳遞 一個(gè) 對(duì)象的引用,使API設(shè)計(jì)的更加簡潔與重復(fù)使用
? 2.this既不指向函數(shù)自身,也不指向函數(shù)的詞法作用域
? 3.實(shí)質(zhì)是在函數(shù)調(diào)用發(fā)生的綁定,指向完全取決于函數(shù)在哪里被調(diào)用
四種綁定方法:
1.默認(rèn)綁定
function foo(){ console.log(this.a); } var a = 2; foo(); //2 // this默認(rèn)指向window
2.隱式綁定
function foo() { console.log(this.a); } var obj = { a: 2, foo: foo } obj.foo(); //2
會(huì)存在隱式丟失綁定對(duì)象,丟失后就成為 默認(rèn)綁定(指向全局對(duì)象)
3.顯示綁定
function foo() { console.log(this.a); } var obj = { a: 2 } foo.call( obj ); //2
通過call(),apply() 顯示綁定,也會(huì)存在綁定丟失問題 call(this,參數(shù)列表),apply(this,args),效果相同,參數(shù)不同硬綁定可以解決,但是一旦綁定,則不能再修改this
4.new綁定
javascript 的 new操作與其 他語言的new操作 很大的不同
new 的四個(gè)實(shí)質(zhì)過程
創(chuàng)一個(gè)全新的對(duì)象
新對(duì)象會(huì)被執(zhí)行[[Prototype]]鏈接
新對(duì)象會(huì)被綁定到函數(shù)調(diào)用的this
若函數(shù)沒有返回其他對(duì)象,new表達(dá)式的函數(shù)調(diào)用會(huì)自動(dòng)返回這個(gè)新對(duì)象
function foo() { this.a = a; } var bar = new foo(2); console.log(bar.a); // 2上面四種綁定的優(yōu)先級(jí)
箭頭函數(shù)的特殊 thisnew綁定 > 顯示綁定 > 隱式綁定 > 默認(rèn)綁定默認(rèn)綁定優(yōu)先級(jí)最低;
顯示綁定比隱式綁定優(yōu)先級(jí)更高
function foo() { console.log(this.a); } var obj1 = { a: 2, foo: foo }; var obj2 = { a: 4, foo: foo }; obj1.foo(); //隱式 2 obj2.foo(); //隱式 4 obj1.foo.call( obj2 ); // 隱式,顯示 同在 顯示優(yōu)先 4 obj2.foo.call( obj1 ); // 2new綁定比隱式綁定優(yōu)先級(jí)更高function foo(some) { this.a = some; } var obj1 = { foo: foo }; var obj2 = {}; obj1.foo(2); console.log(obj1.a); //2 obj1.foo.call(obj2, 3); console.log(obj2.a); //3 var bar = new obj1.foo(4); console.log(obj1.a); // 隱式綁定 2 console.log(bar.a); // new綁定 4new綁定 與 顯示綁定比較function foo(some) { this.a = some; } var obj = {}; var bar = foo.bind(obj1); bar(2); console.log(obj1.a); // 2J var baz = new bar(3); console.log(obj1.a); // 2 console.log(baz.a); // 3 // new 修改了硬綁定 bind()中的this
ES6中特殊函數(shù)類型 箭頭函數(shù) 并不適用于上面四中綁定方式規(guī)則
箭頭函數(shù) 根據(jù)函數(shù)或則全局作用域決定this
function foo() { return (a) => { // this繼承foo console.log(this.a); }; } var ojb1 = { a: 2 } var obj2 = { a: 3 } var bar = foo.call(obj1); bar.call(obj2); // 2foo()的this綁定到obj1,而且bar 的this也會(huì)綁定到obj1 ,箭頭函數(shù)的綁定無法被修改,new 也不能將其修改
var that = this
箭頭函數(shù)
箭頭函數(shù) function foo() { setTimeout(() => { console.log(this.a); //若不適用箭頭函數(shù),則綁定丟失,this默認(rèn)綁定到去全局 為 1 }, 1000); } var obj = { a: 2 }; var a = 1; foo.call(obj);// 2 ****************************************************************************** 使用 that = this function foo() { var that = this; setTimeout(function() { console.log(that.a); //用that傳遞原this的詞法作用域 },1000); } var obj = { a: 2 }; foo.call(obj); //2tips: 兩種風(fēng)格最好不要混合使用,不然很難維護(hù),筆者本人還是比較喜歡使用 that 而不是箭頭函數(shù)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/99972.html
摘要:異步找到書前一個(gè)任務(wù)完成就回電話執(zhí)行回調(diào)函數(shù),而后一個(gè)任務(wù)找書不管前一個(gè)任務(wù)是否完成都會(huì)開始?;卣{(diào)函數(shù)回調(diào)函數(shù)是實(shí)現(xiàn)異步編程的最基本的方法。 JavaScript語言的執(zhí)行環(huán)境是單線程的,即是一次只能完成一個(gè)任務(wù),其他任務(wù)排隊(duì)等候執(zhí)行。只有當(dāng)前一個(gè)任務(wù)完成時(shí),才能開始進(jìn)行下一個(gè)任務(wù)。 這種模式的執(zhí)行環(huán)境簡單,若是遇到一個(gè)耗時(shí)較長的任務(wù),將會(huì)拖延整個(gè)程序的執(zhí)行。 為了解決這個(gè)問題,我們有...
前言 首先出道面試上機(jī)題簡化版(來自喜馬拉雅Fm),侵刪。 **** 你需要在這里完成People的構(gòu)造函數(shù) **** //從而會(huì)按照期望執(zhí)行下面的代碼 var man = new People(小明); var women = new People(小紅) console.log(ma...
摘要:簡介我從七月份開始閱讀源碼,并在隨后的天內(nèi)陸續(xù)更新了篇文章??紤]到超長文章對(duì)讀者不太友好,以及拆分文章工作量也不小等問題。經(jīng)過兩周緊張的排版,一本小小的源碼分析書誕生了。我在寫系列文章中,買了一本書作為參考,這本書是技術(shù)內(nèi)幕。 1.簡介 我從七月份開始閱讀MyBatis源碼,并在隨后的40天內(nèi)陸續(xù)更新了7篇文章。起初,我只是打算通過博客的形式進(jìn)行分享。但在寫作的過程中,發(fā)現(xiàn)要分析的代碼...
摘要:來看代碼上面的代碼不難理解變量是通過構(gòu)造函數(shù)創(chuàng)建的對(duì)象,變量就是一個(gè)很簡單的數(shù)值。一開始,因?yàn)槭峭ㄟ^構(gòu)造函數(shù)創(chuàng)建的對(duì)象,所以值為然后每一次在執(zhí)行的時(shí)候,會(huì)調(diào)用一次的方法。 廢話不多說,我們先來看第一個(gè)例子吧。某天,我遇到了這樣一個(gè)問題:給出變量a和b的定義,使下面三個(gè)語句的輸出結(jié)果都為true。 console.log(ab); 看到題目的我第一反應(yīng)是懵逼的,還有這樣的操作???然后一...
小黃鴨調(diào)試法 場景一:我們都有過向別人(甚至可能向完全不會(huì)編程的人)提問及解釋編程問題的經(jīng)歷,但是很多時(shí)候就在我們解釋的過程中自己卻想到了問題的解決方案,然后對(duì)方卻一臉茫然。 場景二:你的同行跑來問你一個(gè)問題,但是當(dāng)他自己把問題說完,或說到一半的時(shí)候就想出答案走了,留下一臉茫然的你。 其實(shí)上面兩種場景現(xiàn)象就是所謂的小黃鴨調(diào)試法(Rubber Duck Debuging),又稱橡皮鴨調(diào)試法,它是我們...
閱讀 3474·2023-04-25 18:52
閱讀 2486·2021-11-22 15:31
閱讀 1225·2021-10-22 09:54
閱讀 3014·2021-09-29 09:42
閱讀 608·2021-09-26 09:55
閱讀 914·2021-09-13 10:28
閱讀 1106·2019-08-30 15:56
閱讀 2111·2019-08-30 15:55