摘要:大名鼎鼎的作用域和閉包,面試經常會問到。聲明理解閉包,先理解函數的執行過程。閉包的基本結構因為閉包不允許外界直接訪問,所以只能間接訪問函數內部的數據,獲得函數內部數據的使用權。
大名鼎鼎的作用域和閉包,面試經常會問到。閉包(closure)是Javascript語言的一個難點,也是它的特色。
聲明理解閉包,先理解函數的執行過程。
代碼在執行的過程中會有一個預解析的過程,也就是在代碼的執行過程中,會先將代碼讀取到內存中,檢查其是否有錯誤,然后將所有聲明在此進行標記,讓js解析器知道有這樣的一個名字,后面使用時便不會出現未定義的錯誤,這個標記的過程就是提升。
變量的聲明
var num;沒有與之對應的數據,僅僅是讓js解析器知道,你定義了一個num的變量。
函數的聲明
function foo(){};一個獨立的結構,沒有任何語句。首先是將函數名進行提升,讓js解析器知道有一個foo函數,接著是將函數名與函數體連接起來,注意這里并不執行函數體。
代碼演示:
var num = 10; function foo(){ console.log(num); } foo();
預解析的過程(變量提升,函數提升):
var num; function foo(){ console.log(num) } num = 10; foo();
代碼執行時,首先會執行 num = 10; 然后執行foo(),進行函數體,打印出num的值。此時的num訪問到的是全局中定義的num,所以num的值為10.
作用域以上代碼涉及到作用域的問題,所謂的域,表示的是范圍,所以作用域表示的是作用范圍,也就是一個名字在什么地方可以使用,在什么地方不可使用。
1、詞法作用域在js中,采用的是詞法作用域,詞法作用域是指在編寫代碼的過程中體現出來的作用范圍,一旦代碼寫好了,不用執行,作用范圍就確定好了。
Javascript的作用域無非就是兩種:全局變量和局部變量。
2、詞法作用域的規則函數允許訪問函數外的數據
整個代碼結構中只有函數可限定作用域
作用域規則首先使用提升規則分析
若當前作用域中有名字了,就不考慮外面的名字
3、作用域鏈只有函數可以構成作用域結構。只要存在代碼,就至少有一個作用域,即全局作用域。凡是代碼有函數,那么這個函數就構成一個作用域,如果函數中還有函數,那么在這個作用域中就又誕生一個作用域,那么將這樣的所有作用域列出來,就可以有一個:函數內指向函數外的鏈式結構。
作用域鏈變量訪問規則:看變量在當前作用域中,是否有變量的定義與賦值,如果有,則直接使用;如果沒有,則到外面的作用域中查看,如果有,則停止查找,使用外面一層作用域中定義的變量或值,如果沒有,則繼續往外查找,直到最外層的全局,如果全局也沒有定義,則會報錯: xx is not defined。
閉包 什么是閉包閉包,是一個具有封閉功能與包裹功能的一個結構或空間。在js中,函數可以構成閉包。因為函數在當前的作用域中是一個封閉的結構,具有封閉性;同時根據作用域規則,只允許函數內部訪問外部的數據,而外部無法訪問函數內部的數據,即函數具有封閉的對外不公開的特性,就像把一個東西包裹起來一樣,因此函數可以構成閉包。
有點難理解,簡單來說,就是能夠讀取其他函數內部變量的函數,再簡潔一點就是:定義在一個函數內部的函數。
閉包的基本結構因為閉包不允許外界直接訪問,所以只能間接訪問函數內部的數據,獲得函數內部數據的使用權。
function foo(){ var num = 123; function func(){ return num; } return func; } var f = foo(); var res1 = f(); var res2 = f(); // 此時,foo只調用了一次,不會再內存中重新創建一個函數,而通過f,可以訪問并獲取num的值,那么調用f,即可獲得一樣的num值 改良: function foo(){ var num = 123; return function(){ return num; } } var f = foo(); var res1 = f(); var res2 = f(); 再改良: var f = (function foo(){ var num = 123; return function (){ return num; } })(); var res1 = f(); var res2 = f();
function func(){ var num1 = Math.random(); var num2 = Math.random(); return { num1: function(){ return num1; }, num2: function(){ return num2; } } } var p = func(); console.log(p.num1()); console.log(p.num1());// 這兩個訪問到的是同一個隨機數閉包的基本用法
如上面代碼演示的那樣,閉包可以通過返回函數來間接訪問到函數內的數據,這樣,閉包可以實現具有私有訪問空間的函數,保護私有的數據。另一方面,可以幫助其他對象讀取到函數內部的變量
閉包的性能問題函數定義的變量會在函數執行結束后自動回收,但是因為閉包結構引出的數據經常會被外界所引用,這些數據將不會被回收,因此過多的閉包會消耗內存資源,影響性能。所以要謹慎使用閉包,可以在使用閉包時,如果不再使用某些變量了,一定要賦值一個null。
在ES6中,提出來對象代理概念,在代理層操作數據而不是直接操作原數據。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100263.html
摘要:操作符或調用函數時傳入參數的操作都會導致關聯作用域的賦值操作。此外可以使用和來設置對象及其屬性的不可變性級別。忽視這一點會導致許多問題。使用調用函數時會把新對象的屬性關聯到其他對象。 前言 《你不知道的 javascript》是一個前端學習必讀的系列,讓不求甚解的JavaScript開發者迎難而上,深入語言內部,弄清楚JavaScript每一個零部件的用途。本書介紹了該系列的兩個主題:...
摘要:用函數式編程對進行斷舍離當從業的老司機學會函數式編程時,他扔掉了的特性,也不用面向對象了,最后發現了真愛啊作用域和閉包作用域和閉包在里非常重要。旨在幫助非函數式編程的同學,能快速切入到函數式編程的理念。 1、用函數式編程對JavaScript進行斷舍離 當從業20的JavaScript老司機學會函數式編程時,他扔掉了90%的特性,也不用面向對象了,最后發現了真愛啊!!! https:/...
摘要:用函數式編程對進行斷舍離當從業的老司機學會函數式編程時,他扔掉了的特性,也不用面向對象了,最后發現了真愛啊作用域和閉包作用域和閉包在里非常重要。旨在幫助非函數式編程的同學,能快速切入到函數式編程的理念。 1、用函數式編程對JavaScript進行斷舍離 當從業20的JavaScript老司機學會函數式編程時,他扔掉了90%的特性,也不用面向對象了,最后發現了真愛啊!!! https:/...
摘要:用函數式編程對進行斷舍離當從業的老司機學會函數式編程時,他扔掉了的特性,也不用面向對象了,最后發現了真愛啊作用域和閉包作用域和閉包在里非常重要。旨在幫助非函數式編程的同學,能快速切入到函數式編程的理念。 1、用函數式編程對JavaScript進行斷舍離 當從業20的JavaScript老司機學會函數式編程時,他扔掉了90%的特性,也不用面向對象了,最后發現了真愛啊!!! https:/...
摘要:注意由于閉包會額外的附帶函數的作用域內部匿名函數攜帶外部函數的作用域,因此,閉包會比其它函數多占用些內存空間,過度的使用可能會導致內存占用的增加。 作用域和作用域鏈是javascript中非常重要的特性,對于他們的理解直接關系到對于整個javascript體系的理解,而閉包又是對作用域的延伸,也是在實際開發中經常使用的一個特性,實際上,不僅僅是javascript,在很多語言中都...
閱讀 3374·2023-04-26 01:40
閱讀 3080·2021-11-24 09:39
閱讀 1393·2021-10-27 14:19
閱讀 2638·2021-10-12 10:11
閱讀 1298·2021-09-26 09:47
閱讀 1840·2021-09-22 15:21
閱讀 2678·2021-09-06 15:00
閱讀 880·2021-08-10 09:44