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