函式與作用域
1. 函式宣告和函式表示式有什麼區別
- 使用function關鍵字宣告一個函式時,宣告不必放到呼叫的前面。
//函式宣告 function sayHello(){ console.log('hello') } //函式呼叫 sayHello()
函式表示式是把一個匿名函式function()賦給一個變數,宣告必須放到呼叫的前面。//函式宣告 var sayHello = function(){ console.log('hello'); } //函式呼叫 sayHello()
- 函式宣告必須有識別符號,也就是常說的函式名,函式表示式可以省略函式名。
- 用函式宣告建立的函式可以隨時呼叫,而用函式表示式建立的函式是在執行時進行賦值,且要等到表示式賦值完成後才能呼叫。
2. 什麼是變數的宣告前置?什麼是函式的宣告前置
- 在一個作用域下,var 宣告的變數和function 宣告的函式會前置
console.log(a);
//undefinedvar a = 3; console.log(a);
//3sayHello(); function sayHello(){ console.log('hello'); }
執行順序為:var a function sayHello() console.log(a)
//undefineda = 3 console.log(a)
//3sayHello()
- 函式內部的宣告前置。
var a = 1; function main() { console.log(a); var a = 2; } main()
輸出undefined,函式的執行順序如下,變數宣告被提前了。var a = 1; function main() { var a; console.log(a);
//此時a為undefineda = 2; }
- 解析器在向執行環境載入資料時,會率先讀取函式宣告,並使其在執行任何程式碼之前可用,所以存在函式宣告提升,對程式碼求值的時候,js引擎在第一遍會宣告函式並將它們放到原始碼樹的頂部,所以即使呼叫函式的語句在宣告函式的前面也能正常執行。但是對於函式表示式,它必須等到解析器執行到它所在的程式碼行,才會真正被解釋執行。
3. arguments 是什麼
arguments是一個類陣列物件,在函式內部,可以使用arguments物件獲取到該函式的所有傳入引數。
4. 函式的"過載"怎樣實現
JS沒有過載! 同名函式會覆蓋。 但可以在函式體針對不同的引數呼叫執行相應的邏輯。例如:function printPeopleInfo(name, age, sex){ if(name){ console.log(name); } if(age){ console.log(age); } if(sex){ console.log(sex); } } printPeopleInfo('Byron', 26); printPeopleInfo('Byron', 26, 'male');
可以在函式體內部使用if語句,來根據傳遞的引數,執行不同的語句,來模擬函式的過載。
5. 立即執行函式表示式是什麼?有什麼作用
表示式:(function(){ }
)();
立即執行函式就是,宣告一個匿名函式,馬上呼叫這個匿名函式。立即執行函式可以建立一個獨立的作用域,這個作用域裡面的變數,外面訪問不到(即避免變數汙染)。
6. 求n!,用遞迴來實現
function factor(n){ if(n === 1) { return 1 } return n * factor(n-1) } factor(5)
n=5
7. 以下程式碼輸出什麼?
function getInfo(name, age, sex) {
console.log('name:',name);
console.log('age:', age);
console.log('sex:', sex);
console.log(arguments);
arguments[0] = 'valley';
console.log('name', name);
}
getInfo('飢人谷', 2, '男');
getInfo('小谷', 3);
getInfo('男');
function getInfo(name, age, sex) { console.log('name:',name); console.log('age:', age); console.log('sex:', sex); } getInfo('飢人谷', 2, '男');
結果://name: 飢人谷 age: 2 sex: 男getInfo('小谷', 3);
結果://name: 小谷 age: 3 sex: undefinedgetInfo('男');
結果://name: 男 age: undefined sex: undefinedfunction getInfo(name, age, sex) { console.log(arguments); } getInfo('飢人谷', 2, '男');
結果:類陣列 ["飢人谷", 2, "男"]getInfo('小谷', 3);
結果:類陣列 ["小谷", 3]getInfo('男');
結果:類陣列 ["男"]function getInfo(name, age, sex) { arguments[0] = 'valley'; console.log('name', name); } getInfo('飢人谷', 2, '男');
結果:name valleygetInfo('小谷', 3);
結果:name valleygetInfo('男');
結果:name valley
8. 寫一個函式,返回引數的平方和?
function sumOfSquares(num1,num2,num3) { sum = num1*num1+num2*num2+num3*num3; return sum; } var result = sumOfSquares(2,3,4); console.log(result)
//29function sumOfSquares(num1,num2) { sum = num1*num1+num2*num2; return sum; } var result2 = sumOfSquares(1,3); console.log(result2)
//10
9. 如下程式碼的輸出?為什麼
console.log(a);
//結果:undefinedvar a = 1;
console.log(b);
//結果:報錯,b沒有定義。
因為變數宣告會前置,實際順序如下:var a console.log(a); a = 1; console.log(b);
10. 如下程式碼的輸出?為什麼
sayName('world');
//結果:hello worldsayAge(10);
//結果:報錯,sayAge不是一個函式。function sayName(name){ console.log('hello ', name); } var sayAge = function(age){ console.log(age); };
因為函式宣告會前置,但函式表示式只會在執行時才會執行函式,實際順序如下:function sayName(name){ console.log('hello ', name); }
//宣告函式var sayAge
//宣告變數sayName("name")
//呼叫函式sayAge(10);
// 呼叫函式,但按順序函式還未宣告。sayAge = function(age){ console.log(age); };
11. 如下程式碼輸出什麼? 寫出作用域鏈查詢過程虛擬碼
var x = 10 bar() function foo() { console.log(x) } function bar(){ var x = 30 foo() }
結果:10
作用域鏈查詢過程:globalContext { AO: { x: 10, foo: function bar: function }, Scope: null }
//foo.[[scope]] = globalContext.AO
//bar.[[scope]] = globalContext.AO
barContext { AO: { x: 30 foo: function }, Scope: bar.[[scope]] }
fooContext { AO: {}, Scope: foo.[[scope]] }
console.log(x)先從foo 執行上下文中的AO裡找,找不到再從foo的[[scope]]裡找,找到後即呼叫,所以 console.log(x)是 10
12. 如下程式碼輸出什麼? 寫出作用域鏈查詢過程虛擬碼
var x = 10; bar() function bar(){ var x = 30; function foo(){ console.log(x) } foo(); }
結果:30
作用域鏈查詢過程:globalContext { AO: { x: 10 bar: function }, Scope: null } //bar.[[scope]] = globalContext.AO barContext { AO: { x: 30 foo: function }, Scope: bar.[[scope]] } //foo.[[scope]] = barContext.AO fooContext { AO: {}, Scope: foo.[[scope]] }
console.log(x)先從foo 執行上下文中的AO裡找,找不到再從foo的[[scope]]裡找,即是bar的執行上下文,所以 console.log(x)是 30
13. 以下程式碼輸出什麼? 寫出作用域鏈的查詢過程虛擬碼
var x = 10; bar() function bar(){ var x = 30; (function (){ console.log(x) })() }
結果:30
作用域鏈的查詢過程:globalContext { AO: { x: 10 bar: function }, Scope: null } //bar.[[scope]] = globalContext.AO barContext { AO: { x: 30 function: function }, Scope: bar.[[scope]] } //function.[[scope]] = barContext.AO functionContext { AO: {}, Scope: function.[[scope]] }
console.log(x)先從function 執行上下文中的AO裡找,找不到再從function的[[scope]]裡找,即是bar的執行上下文,所以 console.log(x)是 30
14. 以下程式碼輸出什麼? 寫出作用域鏈查詢過程虛擬碼
var a = 1; function fn(){ console.log(a) //僅宣告,未賦值,undefined var a = 5 console.log(a) //賦值為5 a++ //自增變為6 var a
fn3()
//先執行fn3裡的console.log(a),為1fn2()
//再執行fn2裡的console.log(a),為6console.log(a)
//經過fn2,a變為20function fn2(){ console.log(a) //即fnContext.AO = globalContext.AO中的a a = 20 } }
function fn3(){
console.log(a)
//即globalContext.AO中的aa = 200
//globalContext.AO中的a變為200}
fn()
console.log(a)
//呼叫globalContext.AO中的a = 200
結果:
作用域鏈的查詢過程:globalContext { AO: { x: 1 fn: function fn3: function }, Scope: null } //fn.[[scope]] = globalContext.AO //fn3.[[scope]] = globalContext.AO fnContext { AO: { x: 1
//之後a賦值5,再之後a++fn2: function }, Scope: fn.[[scope]] //即globalContext.AO } //fn2.[[scope]] = fnContext.AO fn3Context { AO: { }, Scope: fn3.[[scope]]
//即globalContext.AO}
結果:
undefined
5
1
6
20
200
相關文章
- 函式(三)作用域之變數作用域、函式巢狀中區域性函式作用域、預設值引數作用域函式變數巢狀
- 第 8 節:函式-函式型別與作用域函式型別
- JS內建物件,函式與作用域JS物件函式
- 神奇的函式作用域函式
- javascript基礎(函式與方法的區別,變數作用域,變數和函式的宣告提前,函式作用域)(十五)JavaScript函式變數
- python函式作用域簡介Python函式
- JavaScript塊級作用域宣告函式JavaScript函式
- 作用域安全的建構函式函式
- C語言學習四 — 函式與作用域規則C語言函式
- [JavaScript基礎] 函式,初識作用域JavaScript函式
- JS 總結之函式、作用域鏈JS函式
- Python 函式和變數作用域Python函式變數
- Python中以函式為作用域Python函式
- Python入門(十八):變數作用域與巢狀函式Python變數巢狀函式
- JavaScript 之有趣的函式(函式宣告、呼叫、預解析、作用域)JavaScript函式
- JavaScript 作用域 與 作用域鏈JavaScript
- 1.5.2 Python函式巢狀及作用域Python函式巢狀
- 暫時性死區以及函式作用域函式
- js 函式作用域鏈簡單介紹JS函式
- javascript之作用域與作用域鏈JavaScript
- js的作用域與作用域鏈JS
- ES6箭頭函式和它的作用域函式
- 如何寫一個作用域安全的建構函式函式
- golang常用手冊:陣列、變數作用域、函式Golang陣列變數函式
- JS語法作用域與詞法作用域JS
- 由兩道題擴充套件的對作用域,作用域鏈,閉包,立即執行函式,匿名函式的認識總結套件函式
- 回撥函式的作用與意義函式
- 函式副作用函式
- 塊級作用域替代“匿名立即執行函式表示式(匿名IIFE)”函式
- Python課堂筆記 第7章 包、模組、函式與變數作用域Python筆記函式變數
- javascript函式讀取變數作用域簡單介紹JavaScript函式變數
- Python函式引數傳遞以及變數作用域Python函式變數
- 十二、變數作用域:區域性變數、全域性變數,函式版名片管理系統—新增函式文件變數函式
- 深入理解javascript系列(六):作用域與作用域鏈JavaScript
- JS基礎難點總結(函式作用域,變數提升,物件,建構函式,this)全!!!JS函式變數物件
- js中,函式的閉包、作用域跟[[Scopes]]的關係JS函式
- setInterval()由於作用域問題找不到呼叫函式報錯函式
- JS作用域與閉包JS