填坑-十萬個為什么?(13)

簡介:很多概念不清或忘記,重新構建自己的知識體系。每天問自己1~多個問題。我是菜鳥 成為大神之路!

1. 經典面試題 for(var i=0;i<=3;i++){ setTimeout(function() { console.log(i) }, 10);}打印結果?分析?

for(var i = 0; i < 10; i++) {console.log(new Date(),i);setTimeout(() => {console.log(new Date(),i)}, 1000);//一秒
}
答案:打印1010這道題涉及了異步、作用域、閉包?settimeout是異步執行,1ms后往任務隊列里面添加一個任務,只有主線上的全部執行完,才會執行任務隊列里的任務,
當主線執行完成后,i是10,所以此時再去執行任務隊列里的任務時,i全部是10了。?對于打印10次是:每一次for循環的時候,settimeout都執行一次,但是里面的函數沒有被執行,而是被放到了任務隊列里面,
等待執行,for循環了10次,就放了10次,當主線程執行完成后,才進入任務隊列里面執行。
(注意:for循環從開始到結束的過程,需要維持幾微秒或幾毫秒。)
復制代碼

① 若要輸出從0到9,將 var 改為 let
for(let i = 0; i < 10; i++) {console.log(new Date(),i);setTimeout(() => {console.log(new Date(),i)}, 1000);//一秒
}當我把var 變成let 時
?打印出的是:0~10當解決變量作用域,因為for循環頭部的let不僅將i綁定到for循環快中,
事實上它將其重新綁定到循環體的每一次迭代中,確保上一次迭代結束的值重新被賦值。?setTimeout里面的function()屬于一個新的域,通過 var 定義的變量是無法傳入到這個函數執行域中的,
通過使用 let 來聲明【塊變量】,這時候變量就能作用于這個塊,所以 function就能使用 i 這個變量了;?這個匿名函數的參數作用域 和 for參數的作用域不一樣,是利用了這一點來完成的。
這個匿名函數的作用域有點類似類的屬性,是可以被內層方法使用的。
復制代碼
② 若要輸出從0到9,改寫為閉包

閉包相關解釋下一問。

// 使用閉包
for(var i = 0; i < 10; i++) {console.log(new Date(),i);(function (i) {setTimeout(() => {console.log(new Date(),i);}, 1000);})(i);
}
復制代碼

2.閉包的作用域?代碼執行過程?

經常遇到閉包的相關問題

代碼一:
// 以1問中例子為例
for(var i = 0; i < 10; i++) {console.log(new Date(),i);(function (i) {setTimeout(() => {console.log(new Date(),i);}, 1000);})(i);
}
代碼一是閉包,寫為代碼二不為閉包的形式,(function(i){})(i) '理解為自執行函數' 自執行函數的相關參考在12天和參考文章中,之后我會對著一塊內容進行學習?。代碼二:
var fun = function(x){setTimeout(() => {console.log(new Date(),x);}, 1000);}for(var i = 0; i < 10; i++) {console.log(new Date(),i);fun(i);
}
復制代碼
JavaScript 變量可以是局部變量或全局變量。
私有變量可以用到閉包。什么是閉包:
> 就是函數的局部變量集合,只是這些局部變量在函數返回后會繼續存在。
> 就是函數的“堆棧”在函數返回后并不釋放,我們也可以理解為這些函數堆棧并不在棧上分配而是在堆上分配
> 當在一個函數內定義另外一個函數就會產生閉包
> "注:變量聲明時如果不使用 var 關鍵字,那么它就是一個全局變量,即便它在函數內定義。"注意:通常人們對閉包的理解是不完全的,認為在 JavaScript 中只有嵌入的函數才是閉包。但其實任何擁有 free variable(自由變量)
的函數都是以閉包的形式存在的。因為本質上,閉包是 free variable 問題的一種解決方案。http://liximomo.github.io/javascript-closure閉包的注意點
1)由于閉包會使得函數中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導致內存泄露。
解決方法是,在退出函數之前,將不使用的局部變量全部刪除。
2)閉包會在父函數外部,改變父函數內部變量的值。所以,如果你把父函數當作對象(object)使用,把閉包當作它的公用方法(Public Method),
把內部變量當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數內部變量的值。
復制代碼

閉包需要注意的兩種情況----函數作為返回值,函數作為參數傳遞。

例子:函數作為返回值

1. function greeting(name) {
2. 		var text = 'Hello '; // local variable// 每次調用時,產生閉包,并返回內部函數對象給調用者
3. 		return function() {return text += name; }}4. 	var sayHello=greeting("Closure");5. 	document.write(sayHello());
6. 	document.write("<br>");
7. 	document.write(sayHello());
8. 	document.write("<br>");
9. 	document.write(sayHello());
10. document.write("<br>");
11. document.write(sayHello());
12. document.write("<br>");
13. document.write(sayHello());// 通過閉包訪問到了局部變量text代碼解析:
> 執行第4行時第一行的函數運行一次,返回內嵌函數引用作為第4行sayHello變量的值。
> 之后的第5到13行執行的函數操作其實只是執行sayHello指向的函數(即返回的內嵌函數)。
> 解釋text為什么能自增,閉包的概念。復制代碼

例子:函數作為參數傳遞

1. var num = 10;2. var fun = function(var num){
3.    console.log(num);}
4. !function(f){
5.     var num = 100;
6.     f(num);
7. }(fun)代碼解析:
> 第四行'!'表示高優先級,被'!'標注的先執行。
> 第7行將fun指向的引用2行函數傳給參數f在函數中執行f(?)函數,此時log出來的值是10。
> 解釋看js作用域
復制代碼

3.var let const的區別?

① 什么是var的變量提升補充2019年1月5日23:31:41 來源網易課堂
'代碼1'
var a = 10;
function foo(){console.log(a);//打印:10
}
'代碼2'
var a = 10;
function foo(){console.log(a);//打印:undefinedvar a = 5;
}
'問代碼2為什么輸出的是undefined這里變量提前了,實際代碼相當于如下'
'代碼3'
var a = 10;
function foo(){var a;console.log(a);//打印:undefineda = 5;
}
復制代碼
② let 聲明的變量只在它所在的代碼塊有效
function demo(){{var a = 12;let c = 10;console.log(a);//這里會打印出12;console.log(c);//這里會打印出10;}console.log(a);//這里會打印出12console.log(c);//這里打印出的內容為 "c is not defined";//說明聲明的c變量只在{}代碼塊中能夠訪問,其他地方都訪問不到;
}
demo();
復制代碼
③ let不存在變量提升

let 不像var 那樣會發生 '變量提升' 現象,因此,變量需要先聲明然后再使用,否則報錯;

// var 的情況
console.log(vardata);  // undefined
var vardata = 2;// let的情況;
console.log(letdata);  // letdata is not defined 報錯
let letdata = 2;
復制代碼
④ let暫時性死區

快級作用域內存在let命令,它所聲明的變量就綁定在這個區域,不再受外部影響;

var tmp = 123;
if (true) {tmp = 'abc';let tmp;console.log(tmp); // tmp is not defined
}
復制代碼
⑤ let不允許重復聲明

let 不允許在相同作用域內,重復聲明同一個變量。

function foo() {let v = 10;var v = 1;//Identifier 'v' has already been declaredconsole.log(v);
}
foo();function foo1() {let v1 = 10;let v1 = 1;//Identifier 'v1' has already been declaredconsole.log(v1);
}
foo1();
復制代碼
⑥ const 聲明一個只讀的常量,一旦聲明,常量的值就不允許改變
⑦ const 一旦聲明了變量,就必須初始化,不能留到以后賦值。如果使用const聲明一個變量,但是不賦值,也會報錯
⑧ const 的作用域與let命令相同;只在聲明所在的塊級作用域內有效。
⑨ const 不可重復聲明 (和let一樣)

參考文章:
① let的含義及let與var的區別
② 閉包文檔
③ 博客-深入理解javascript原型和閉包
④ JS關于閉包
⑤ 函數 + 函數創建時的環境 = 閉包

轉載于:https://juejin.im/post/5c26e9cbe51d450cfe737dae

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/252706.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/252706.shtml
英文地址,請注明出處:http://en.pswp.cn/news/252706.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

WordPress分類列表函數:wp_list_categories用法及參數詳解舉例

http://www.511yj.com/wordpress-wp-categories.html 注意&#xff1a; 1、 wp_list_categories() 和 list_cats() 以及 wp_list_cats() 的使用類似&#xff0c;但是后面 2 個已經棄用。 2、如果你希望不格式化輸出分類&#xff0c;請使用 get_categories() 3、因為 WordPress …

DVP,LVDS和MIPI

Mipi 接口 和 LVDS 接口區別 主要區別&#xff1a; 1. LVDS接口只用于傳輸視頻數據&#xff0c;MIPI DSI不僅能夠傳輸視頻數據&#xff0c;還能傳輸控制指令&#xff1b; 2. LVDS接口主要是將RGB TTL信號按照SPWG/JEIDA格式轉換成LVDS信號進行傳輸&#xff0c;MIPI DSI接口則…

安裝Cornerstone3.1注意點

mac在升級之后就不能社會做任何來源安裝,需要在終端運行 sudo spctl --master-disable//添加任何來源的,再次安裝就可以的轉載于:https://www.cnblogs.com/chengenyan/p/6835970.html

2019我的目標

1 能考上自己理想的高中 2 至少學會一直種語言&#xff08;英語&#xff09; 3 堅持記錄每一天&#xff0c;每個星期至少寫一遍文章 4 堅持到底 轉載于:https://www.cnblogs.com/ta20/p/10203974.html

nodejs開發——require與exports的使用

nodejs開發——require與exports的使用 另一片文章總結&#xff1a;http://www.cnblogs.com/hfultrastrong/p/8036682.html require require函數用于在當前模塊中加載和使用別的模塊&#xff0c;傳入一個模塊名&#xff0c;返回一個模塊導出對象。模塊名可使用相對路徑&#x…

jvm 內存溢出問題排查方法

如果你做TCP通訊或者map集合操作&#xff0c;并發處理等功能時&#xff0c;很容易出現 Java 內存溢出的問題。本篇文章&#xff0c;帶領大家深入jvm&#xff0c;分析并找出jvm內存溢出的代碼。 jvm中除了程序計數器&#xff0c;其他的區域都有可能會發生內存溢出 內存溢出是什么…

一個go1.9.x 編譯器內聯引起的棧信息錯亂的問題分析

2019獨角獸企業重金招聘Python工程師標準>>> 背景是在寫個日志庫&#xff0c;日志庫有個很重要的功能就是要打印出調用棧&#xff0c;知道具體是哪個文件&#xff0c;哪個函數調用的Info 等。 然后在測試中發現了一種寫法&#xff0c;我自己本機測試一直ok&#xff…

CMOS Sensor的調試經驗分享

轉自&#xff1a;http://bbs.52rd.com/forum.php?modviewthread&tid276351 CMOS Sensor的調試經驗分享      我這里要介紹的就是CMOS攝像頭的一些調試經驗。   首先&#xff0c;要認識CMOS攝像頭的結構。我們通常拿到的是集成封裝好的模組&#xff0c;一般由三個部…

Learn Python—表達式、數據類型、流程控制

表達式 在 Python 中&#xff0c;2 2 稱為“表達式”&#xff0c;它是語言中最基本的編程結構。表達式包含“值”&#xff08;例如2&#xff09;和“操作符”&#xff08;例如&#xff09;&#xff0c;并且總是可以求值&#xff08;也就是歸約&#xff09;為單個值。這意味著在…

監控工具之zabbix server3.4 部署配置

[rootlocalhost src]# cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core) [rootlocalhost src]# pwd /usr/local/src 配置zabbix的yum源 [rootlocalhost src]# rpm -ivh http://repo.zabbix.com/zabbix/3.4/rhel/7/x86_64/zabbix-release-3.4-2.el7.noarch.rpm …

CMOS Sensor基礎知識

CMOS Sensor基礎知識 曝光時間以行長為單位&#xff1b; PCLK以Hz為單位&#xff1b; 行長以周期數為單位&#xff0c;幀長以行長數為單位&#xff1b;其中周期數就是頻率 T 周期以ms為單位&#xff1b; f 頻率以Hz為單位&#xff1b; f 1 / T&#xff1b; Vsync Dummy Line…

java獲取mp3的時長和播放mp3文件

所需包為jaudiotagger-2.2.6-SNAPSHOT.jar和jl1.0.1.jar。 import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream;import org.jaudiotagger.audio.AudioFileIO; import org.jaudiotagger.audio.mp3.MP3AudioHeader; import org.jaudiotag…

Redis 優缺點

REmote DIctionary Server(Redis) 是一個由Salvatore Sanfilippo寫的key-value存儲系統。 Redis是一個開源的使用ANSI C語言編寫、遵守BSD協議、支持網絡、可基于內存亦可持久化的日志型、Key-Value數據庫&#xff0c;并提供多種語言的API。 Redis 與其他 key - value 緩存產品…

Python并發編程之concurrent.futures

2019獨角獸企業重金招聘Python工程師標準>>> concurrent.futures模塊提供了一個異步執行callables的高級接口。 可以使用ThreadPoolExecutor和ProcessPoolExecutor。 兩者都繼承了相同的接口&#xff0c;該接口由抽象的Executor類定義。 一個抽象類&#xff0c;提供…

1.3鏈表

鏈表的物理存儲結構是用一組地址任意的存儲單元存儲數據的。不像順序表占據連續的一段內存空間&#xff0c;而是將存儲單元分散在內存的任意地址上。 鏈表結構中&#xff0c;每個數據元素記錄都存放到鏈表的一個節點&#xff08;node&#xff09;中&#xff0c;而每個節點之間由…

移植opencv3.20到3556AV100

1.移植環境&#xff1a; Ubuntu14.04 arm-hisiv200-linux-opencv3.20 下載地址 2.移植步驟&#xff1a; 1&#xff09;安裝cmake-gui 2&#xff09;新建一個opencv目錄存放opencv-3.2.0.zip&#xff0c;并解壓 擊Browse Source選擇~/hisi/opencv/opencv-3.2.0 點擊Brow…

ngnix 詳解

4 Nginx的rpm軟件包安裝 4.1 安裝包在位置 D:\講課內容--\新巴巴運動網\nginx高并發解決\nginx安裝包 4.2 此種安裝方式不用安裝gcc等編譯工具 4.3 安裝命令如下 rpm –ivh nginx 5 配置虛擬主機 5.1 什么是虛擬主機 虛擬主機是一種特殊的軟硬件技術&#xff0c;它可以將網絡上…

iscroll5制作上下拉刷新 tab出現的問題

1.iscoll5插件刷新后如果想改變現實位置如果向下幾px可以用 myScroll.scrollBy(0,0);方法&#xff0c;該值是相對當前位置。 2.iscoll5用到tab的時候&#xff0c;用點擊生成iscoll對象出現取消不了之前的對象的綁定事件&#xff0c;點擊多次后刷新執行多次的問題&#xff0c;解…

初談邏輯讀、物理讀、預讀

前言&#xff1a; 該文并不全是本人原創&#xff0c;里面的某些原理來自于CareySon。 SQL SERVER數據存儲的形式 要理解邏輯讀、物理讀、預讀這三個概念&#xff0c;先要搞懂SQL Server的數據存儲方式。 SQL Server數據庫包括數據文件和日志文件&#xff0c;一個數據庫可以有一…

Makefile常用萬能模板(包括靜態鏈接庫、動態鏈接庫、可執行文件)

1、生成可執行文件的makefile2、生成靜態鏈接庫的makefile3、生成動態鏈接庫的makefile 本文把makefile 分成了三份&#xff1a;生成可執行文件的makefile&#xff0c;生成靜態鏈接庫的makefile&#xff0c;生成動態鏈接庫的makefile。 這些makefile都很簡單&#xff0c;一般都…