函數聲明和函數表達式有什么區別
聲明一個函數有三種方式
1.用function聲明一個函數:
2.函數表達式方法:
3.function構造函數的方法(一般不使用):
因為變量提升的原因,函數表達式的方法提升的是var print,所以用function聲明的函數在執行時,會把函數提升到js語句的頂部,所以即使函數調用出現在函數聲明的前面,也不會出現報錯;而用函數表達式的方法聲明的函數提升的是var定義的變量,所以會報錯。
什么是變量的聲明前置?什么是函數的聲明前置
JS語言的特性是JS引擎在解析JS代碼時會先獲取所有被聲明的變量然后再一行一行的運行,所以所有var聲明的變量和function聲明的函數會前置到代碼頭部,所以使用或調用在其后的變量或函數也不會報錯
arguments 是什么
arguments是一個類數組對象,對應于傳遞給函數的參數,可以通過索引的方式訪問函數傳入的參數,arguments[i],i為數組中元素的索引
函數的"重載"怎樣實現
JS里因為同名函數會被覆蓋所以沒有重載,但是可以在函數體針對不同的參數調用執行相應的邏輯(模擬重載)
注意:傳參時需注意傳入參數的順序
立即執行函數表達式是什么?有什么作用
立即執行函數的作用是隔離作用域,使被執行的函數內部的變量不會污染到外部,即外部不能訪問函數內部的變量。寫法:
(function fn(){})()
[function fn(){}]()
!function fn(){}()
求n!,用遞歸來實現
打印結果:
寫一個函數,返回參數的平方和?
如下代碼的輸出?為什么
console.log(a);
var a = 1;
console.log(b);
因為聲明前置,所以上面代碼等價于:
var a
console.log(a);
a = 1;
console.log(b);
所以console.log(a)輸出 undefined
console.log(b)輸出b is not defined
如下代碼的輸出?為什么
sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
聲明前置所以代碼等價于:
function sayName(name){
console.log('hello ', name);
}
var sayAge
sayName('world');
sayAge(10);
sayAge = function(age){
console.log(age);
};
所以sayName('world');輸出 hello world
sayAge(10);輸出 sayAge is not a function
如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
var x = 10
bar()
function foo() {
console.log(x)
}
function bar(){
var x = 30
foo()
}
偽代碼:
1.globalContext = {
AO: {
x: 10
foo: function(){}
bar: function(){}
}
Scope: null
}
// 聲明 foo 時 得到下面
foo.[[scope]] = globalContext.AO
bar.[[scope]] = globalContext.AO
//調用bar()時 進入bar()的執行上下文
2. barContext={
AO: {
x:30
}
bar.[[scope]] = globalContext.AO
}
//調用foo()時 進入foo()的執行上下文
3. fooContext={
AO:{ }
foo.[[scope]] = globalContext.AO
}
foo( )的x是globalContext的x 所以輸出10
如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
var x = 10;
bar()
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
}
偽代碼:
1.globalContext = {
AO: {
x: 10
bar: function(){}
}
Scope: null
}
// 聲明 bar 時 得到下面
bar.[[scope]] = globalContext.AO
2. barContext = {
AO: {
x: 30,
foo: function
},
Scope: bar.[[scope]] //globalContext.AO
}
foo.[[scope]] = barContext.AO
3. fooContext = {
AO: {},
Scope: foo.[[scope]] // barContext.AO
}
調用foo( )時先在foo的AO里找,找不到再去bar的AO里找 所以輸出30
如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
var x = 10;
bar()
function bar(){
var x = 30;
(function (){
console.log(x)
})()
}
執行過程同上一題但是bar內嵌套的是一個立即執行函數聲明以后立即調用并執行自身同時其內部沒有x變量所以會去bar的AO里找所以輸出 30
如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
var a = 1;
function fn(){
console.log(a)
var a = 5
console.log(a)
a++
var a
fn3()
fn2()
console.log(a)
function fn2(){
console.log(a)
a = 20
}
}
function fn3(){
console.log(a)
a = 200
}
fn()
console.log(a)
聲明前置后:
var a = 1;
function fn(){
var a
console.log(a)
a = 5
console.log(a)
a++
fn3()
fn2()
console.log(a)
function fn2(){
console.log(a)
a = 20
}
}
function fn3(){
console.log(a)
a = 200
}
執行過程如下:調用fn( )后進入其執行上下文,首先var a但未賦值所以打印undefined后 a=5所以打印5,a++此時fn內部a為6,調用fn3時進入fn3的執行上下文首先打印1后a=200污染了全局變量a,執行完退出調用fn2進入fn2的執行上下文打印6,執行a=20污染了fn內部的變量a所以打印出20最后在打印200