筆記~筆記~克服 JS 的奇怪部分
開始之前
-
為什麼要了解Hoisting??
因為面試會考?
因為大家都說重要?
因為想更了解javascript?
因為有助於debug?
因為想變強?
-
要怎麼做??
上網google大神們的文章/討論?
去書店翻書?(犀牛書….)
讀書會交流?
找線上課程?
小測驗先:
console.log('name is', name);
var name;
console.log('name is', name);
name='peng';
console.log('name is', name);
// 1.
console.log(a);
// 沒有宣告a變數 就要取值....找不到
// ReferenceError: a is not defined
// 2.
console.log(b);
var b=1;
// undefined
// 逐行執行 why why why
// Hoisting造成!!
// 3. 好似code被搬移
var b;
console.log(b);
b=1;
// 變數的宣告被提升 賦值不會!
了解Javascript 運作前…..
- 直譯/編譯?
Javascript為直譯式的程式語言,代表code不需要先compile才能執行
但電腦如何知道script中敘述的code要做什麼?
因為……
這是Javascript engine的工作
Javascript 引擎負責轉譯我們的source code,並執行轉譯後的結果
遙想…..開始寫javascript時,不需要安裝任何額外的軟體
因為現在每一個瀏覽器都有Javascript engine, 可以很輕鬆的執行我們寫的script!
- Chrome V8: google chrome
- SpiderMonkey: Firefox
- Nitro: Safari
- Chakra: Edge
基本概念
1.Syntax parser-語法解析器
A Program that reads your code and determines what it does and if its grammar is valid.
逐字讀取我們所撰寫的程式碼,解析語法是否正確,轉譯成電腦指令.
中間的角色: 編譯器/ 直譯器 »>語法解析器
也就是browser中javascript engine負責!
2.Execution context-執行環境
A wrapper to help manage the code that is running.
幫助管理正在執行的程式
想像很多個lexical environment, 決定現在該執行哪個
3.Lexical environment-詞彙環境
Where something sits physically in the code you write.
程式碼在程式中實際的位置.
對javascript,程式碼寫的位置不同代表不同意思,所謂的詞彙環境就顯得很重要
不是每個程式語言都存詞彙環境!!
依code所在位置、周圍環境,幫助解析器決定變數/函數
根據詞彙環境幫助我們想像變數/函數在電腦記憶體的位置!!
function hello(){
var a ="hello";
}
//不同於
var a="hello";
function hello(){
}
Global execution context-全域執行環境
the javascript engine creates the global execution context before it starts to execute any code.
可以在任何地方取用
初始化時,會創造global object以及變數this (不需程式碼 就被創造)
執行javascript時,永遠會有一個全域物件
(for browser» window物件; 每個視窗有各自的執行環境自己的全域物件)
全域環境下,this變數參照到global object(window)
如果變數和物件不在函數中,就是全域物件~
ex:即使執行一個空的js file–>browser中JS engine解析js file–>執行環境被建立–>global object(window)和this被建立
**還有第三個建立的東西 outer environment…. **
所以執行環境???
Hoisting 即執行環境的creation階段做的事
var a ="hihihihi"
function b(){
console.log('called b');
}
b();
console.log(a);
// >called b
// >hihihihi
b();
console.log(a);
var a ="hihihihi"
function b(){
console.log('called b');
}
// 某些程式會報錯>>> 未宣告就要用b
// output
// >called b
// >undefined
網路解釋: javascript的變數和函數被提升到程式碼最上面
不能說錯但….容易造成誤解…程式碼會搬動?
執行環境運作
執行環境被分兩階段建立
-
creation phase
全域物件和this存在記憶體中& 創造外部環境
setup memory space for variables and function
這個步驟稱為hoisting
逐行執行前 替變數&函數在記憶體中建立一個空間
當程式被逐行執行時, 才可以找到這些變數或函數
// 函數也會被hoisting // 建立函數常用兩種方式 Function declarations/ Function expressions funciton abc (){ // bla bla } var a =function (){ // bla bla } // 匿名函數當作值 指定給變數 // 如果hoisting不存在 abc(); function abc(){ //blablabla } // 就不能用 // Function expressions // 僅有var a 被hoisting
加映
宣告變數&函數的順位
Variable assignment takes precedence over function declaration.
Function declarations take precedence over variable declarations.
變數的賦值>函數的宣告>變數的宣告
function name(){ console.log('called name'); } var name; console.log(name); // function name(){ console.log('called name'); } var name=2; console.log(name);
-
execution phase
逐行執行程式碼
function b(){
console.log('called b!')
}
b();
console.log(a);
var a ='hihihiihihi';
console.log(a);
// 將function b & variable a在記憶體建立空間(只有空間 沒有值 沒有內容)
// 呼叫b() 建立function b 執行環境
// 印出 'called b'
// 找出a的值 並印出
// 將'hihihiihihi'賦值給變數a (a的記憶體位址指向字串hihihiihihi)
// 找出a的值 並印出
單執行緒&同步執行
javascript不是瀏覽器唯一的東西
javascript為單執行緒不是指瀏覽器,
單執行緒(single threaded): one command at a time
同步(synchronous): one at a time 程式碼會依照出現順序一次執行一行
////同步
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);
output:// 1 2 3 4 5
////非同步
function asyncConsole(time,value){
setTimeout(function(){console.log(value);},time);
}
asyncConsole(200,1);
asyncConsole(100,2);
asyncConsole(400,3);
asyncConsole(500,4);
asyncConsole(300,5);
output:// 2 1 5 3 4
////
函數呼叫&執行堆
function b(){
}
function a(){
b();
}
a();
呼叫function–>一個新的執行環境創造–>被放進stack中
誰在最上面就是就是正在執行的東西
會有自己的記憶體空間給變數和函數
補充 event loop
函數&環境&變數環境
- 變數環境:描述創造變數的位置以及和其他變數的關係
function b(){
var myvar;
console.log(myvar);
}
function a(){
var myvar=2; // 創造myvar在自己的變數環境中
console.log(myvar);
b(); // 呼叫函數 創造出他的執行環境
}
var myvar=1;
console.log(myvar);
a();
console.log(myvar);
scope chain
scope:能取用變數的地方
chain: 外部環境參照的連結
function b(){
console.log(myvar);
}
// 從詞彙上來看, 在全域環境中!
function a (){
var myvar=2;
b();
}
var myvar=1
a();
處理變數時, javascript 不只會在執行環境的變數環境中尋找
外部環境的參照
每個執行環境都有一個外部環境
當你需要某個執行環境內的程式碼變數, 如果找不到變數, 他會到外部環境尋找變數
外部環境是根據函數實際上的位置
function a (){
var myvar=2;
function b(){
console.log(myvar);
}
// 從詞彙上來看, a()環境中!
// 外部參照為a()
}
var myvar=1
a();
範例
function test(){
console.log();
console.log(foo());
var a=1;
function foo(){
return 2;
}
}
test();
// 全域環境下:宣告函數test
// 呼叫test()
// 建立test執行環境
// 宣告a變數及foo函數
// 印出() >>> undefined
// 呼叫foo() 並印出
// 建立foo執行環境
// 逐行執行 回傳2
// event loop
(function() {
console.log(1);
setTimeout(function(){console.log(2)}, 1000);
setTimeout(function(){console.log(3)}, 0);
console.log(4);
})();
// hoisting
var salary = "1000$";
(function () {
console.log("Original salary was " + salary);
var salary = "5000$";
console.log("My New Salary " + salary);
})();
// hoisting
function foo(){
function bar() {
return 3;
}
return bar();
function bar() {
return 8;
}
}
alert(foo());
題外話-Javascript發展歷史
1990-1999
-
1990
第一個web browser WorldWideWeb, 由Tim Berners Lee開發 (後來改名Nexus)
-
1993
Marc Andreessen and Eric Bina 開發Mosaic Browser
-
1994
-
Marc 成立網景
- 網景推出第一款Netscape Navigator瀏覽器, 市佔達70%
- 微軟發展自家瀏覽器IE, 搭著windows 95一起
-
-
1995
- 網景公司瀏覽器市占80%
-
微軟進軍瀏覽器市場(買作業系統送IE瀏覽器)
- Brendan Eich 在面對微軟的壓力之下,利用10天創造出名為Mocha的語言
- 為了市場考量,改名為Javascript
- 1996
- 微軟發布JScript (模仿Javascript語言的產品)
- Netscape(網景)公司向ECMA國際組織提交Javascript (搶當標準~)
-
1997
產生第一個Javascript標準規範(ES1),ECMA-262/ECMAScript
-
1998-第一次瀏覽器大戰
- IE取得瀏覽器市場90%
-
因壟斷微軟遭政府起訴 (在自家作業系統綁定IE瀏覽器)-反托拉斯法
- 發布ES2
- 網景公司被AOL收購
- 網景開放瀏覽器及相關產品的原始碼 (Mozila基金會Firefox的前身)
-
1999
發布ES3
2000-2008
-
2000開始…..
- ES4,加入classes, interface…等很大幅度的改變,被認為太複雜……擱置…..
- 微軟IE仍是瀏覽器市場第一(不太甩ECMAScript,在自己的瀏覽器中用自己的JS新功能)
-
2002
IE瀏覽器達到90%以上的市場佔有率
-
2003
- Apple發佈Safari瀏覽器 (支援Mac平台外,也支援Windows作業系統)
- 網景公司解散
- 2004-第二次瀏覽器大戰
- Mozilla基金會發表Firefox 1.0瀏覽器
- Opera瀏覽器,與Mozilla共同參與了推動瀏覽器相關規格的開放標準化
- 對戰Microsoft
-
2006
John Resig開發了JQuery
-
2008
Google進軍瀏覽器市場釋出chrome瀏覽器以及V8 engine(開放其原始碼)
2009-2015
-
2009
-
Ryan Dahl利用google的V8 Project開發NodeJS
-
隔了10年, 發布了ES5
-
-
2010
AngularJS和Backbone框架出現
- 2012
- Chrome超越IE, 成為世界上使用最多的瀏覽器
- apple停止safari for windows
-
2013
-
Facebook釋出ReactJS
-
在這段期間frontend, backend, and fullstack框架出現
( Angular, Ember, Meteor, Sails, Vue, Svelte, Mithril, Knockout, Polymer…)
-
2015-Now
-
2015
-
ES6釋出
-
微軟發布Edge(成為win 10 預設瀏覽器)
-
-
2016
ES7釋出
-
2017
ES8釋出
-
2018
ES9釋出
延伸閱讀&參考圖文
Udemy-課程-克服JS的奇怪地方
The JavaScript runtime environment
The Weird History of JavaScript