1.函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別
function命令聲明的代碼區(qū)塊,就是一個函數(shù)纽竣。function命令后面是函數(shù)名坠韩,函數(shù)名后面是一對圓括號,里面是傳入函數(shù)的參數(shù)孕暇。函數(shù)體放在大括號里面仑撞。
function print(s) {
console.log(s);
}```
除了用function命令聲明函數(shù),還可以采用變量賦值的寫法妖滔。
var print = function(s) {
console.log(s);
};```
這種寫法將一個匿名函數(shù)賦值給變量隧哮。這時,這個匿名函數(shù)又稱函數(shù)表達(dá)式(Function Expression)座舍,因?yàn)橘x值語句的等號右側(cè)只能放表達(dá)式近迁。
函數(shù)的表達(dá)式需要在語句的結(jié)尾加上分號,表示語句結(jié)束簸州。而函數(shù)的聲明在結(jié)尾的大括號后面不用加分號鉴竭。
區(qū)別:
函數(shù)聲明:聲明不必放到調(diào)用的前面
函數(shù)表達(dá)式:聲明必須放到調(diào)用的前面
JavaScript 解釋器中存在一種變量聲明被提升(hoisting)的機(jī)制,也就是說變量(函數(shù))的聲明會被提升到作用域的最前面岸浑,即使寫代碼的時候是寫在最后面搏存,也還是會被提升至最前面。
例如以下代碼段:
alert(foo); // function foo() {}
alert(bar); // undefined
function foo() {}
var bar = function bar_fn() {};
alert(foo); // function foo() {}
alert(bar); // function bar_fn() {}```
輸出結(jié)果分別是function foo() {}矢洲、undefined璧眠、function foo() {}和function bar_fn() {}。
可以看到 foo 的聲明是寫在 alert 之后读虏,仍然可以被正確調(diào)用责静,因?yàn)?JavaScript 解釋器會將其提升到 alert 前面,而以函數(shù)表達(dá)式創(chuàng)建的函數(shù) bar 則不享受此待遇盖桥。
# 2.什么是變量的聲明前置灾螃?什么是函數(shù)的聲明前置
在一個作用域下,var 聲明的變量和function 聲明的函數(shù)會前置
與全局作用域一樣揩徊,函數(shù)作用域內(nèi)部也會產(chǎn)生“變量提升”現(xiàn)象腰鬼。var命令聲明的變量嵌赠,不管在什么位置,變量聲明都會被提升到函數(shù)體的頭部熄赡。
# 3.arguments 是什么
由于JavaScript允許函數(shù)有不定數(shù)目的參數(shù)姜挺,所以我們需要一種機(jī)制,可以在函數(shù)體內(nèi)部讀取所有參數(shù)彼硫。這就是arguments對象的由來炊豪。
arguments對象包含了函數(shù)運(yùn)行時的所有參數(shù),arguments[0]就是第一個參數(shù)拧篮,arguments[1]就是第二個參數(shù)词渤,以此類推。這個對象只有在函數(shù)體內(nèi)部他托,才可以使用掖肋。
# 4.函數(shù)的"重載"怎樣實(shí)現(xiàn)
>函數(shù)重載(英語:Function overloading),是Ada赏参、C++志笼、C#、D和Java等編程語言中具有的一項(xiàng)特性把篓,這項(xiàng)特性允許創(chuàng)建數(shù)項(xiàng)名稱相同但功能的輸入輸出類型不同的子程序纫溃,它可以簡單地稱為一個單獨(dú)功能可以執(zhí)行多項(xiàng)任務(wù)的能力。
其他語言重載范例
int sum(int num1, int num2){
return num1 + num2;
}
float sum(float num1, float num2){
return num1 + num2;
}
sum(1, 2);
sum(1.5, 2.4);
Javascript中韧掩,先定義的函數(shù)紊浩,會被后定義的函數(shù)覆蓋。因此Javascript不支持函數(shù)的重載疗锐,不能夠定義同樣的函數(shù)然后通過編譯器去根據(jù)不同的參數(shù)執(zhí)行不同的函數(shù)坊谁。
但是javascript卻可以通過自身屬性去模擬函數(shù)重載。
變相實(shí)現(xiàn)函數(shù)重載的方法:
- 利用arguments對象
<script type="text/javascript">
function showSum()
{
//使用arguments對象模擬出重載效果
if (arguments.length == 1)
{
alert(arguments[0] + 1);
}
else if (arguments.length == 2)
{
alert(arguments[0] + arguments[1]);
}
else if (arguments.length == 3)
{
alert(arguments[0] + arguments[1] + arguments[2]);
}
else {
alert('請傳入?yún)?shù)滑臊!');
}
}
//顯示101
showSum(100);
//顯示200
showSum(100, 100);
//顯示300
showSum(100, 100,100);
</script>```
- 利用閉包(有點(diǎn)難口芍,學(xué)學(xué)回來再看。)
參考文章:http://www.cnblogs.com/yugege/p/5539020.html
參考文章:https://johnresig.com/blog/javascript-method-overloading/
參考文章:http://www.cnblogs.com/bluedream2009/archive/2011/01/05/1925963.html
5.立即執(zhí)行函數(shù)表達(dá)式是什么雇卷?有什么作用
立即執(zhí)行函數(shù)就是
1.聲明一個匿名函數(shù)
2.馬上調(diào)用這個匿名函數(shù)
JavaScript引擎規(guī)定鬓椭,如果function關(guān)鍵字出現(xiàn)在行首,一律解釋成語句关划,為了兼容 JS 的語法小染。避免瀏覽器報(bào)語法錯誤,可以這樣寫:
(function(){alert('我是匿名函數(shù)')} ()) // 用括號把整個表達(dá)式包起來
(function(){alert('我是匿名函數(shù)')}) () //用括號把函數(shù)包起來
!function(){alert('我是匿名函數(shù)')}() // 求反贮折,我們不在意值是多少裤翩,只想通過語法檢查。
+function(){alert('我是匿名函數(shù)')}()
-function(){alert('我是匿名函數(shù)')}()
~function(){alert('我是匿名函數(shù)')}()
void function(){alert('我是匿名函數(shù)')}()
new function(){alert('我是匿名函數(shù)')}()
只有一個作用:創(chuàng)建一個獨(dú)立的作用域脱货。
這個作用域里面的變量岛都,外面訪問不到(即避免「變量污染」)律姨。
參考文章:https://zhuanlan.zhihu.com/p/22465092
6.求n!振峻,用遞歸來實(shí)現(xiàn)
function factor(n){
if(n === 1) {
return 1;
}
return n * factor(n-1);
}
factor(5);
注意:求遞歸的時候要考慮負(fù)數(shù)和0臼疫;
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('男');
name: 饑人谷
age: 2
sex: 男
["饑人谷", 2, "男", callee: function, Symbol(Symbol.iterator): function]
name valley
name: 小谷
age: 3
sex: undefined
["小谷", 3, callee: function, Symbol(Symbol.iterator): function]
name valley
name: 男
age: undefined
sex: undefined
["男", callee: function, Symbol(Symbol.iterator): function]
name valley
8 寫一個函數(shù)扣孟,返回參數(shù)的平方和烫堤?
function sumOfSquares(){
var sum = 0;
for (var i = 0; i<arguments.length; i++) {
sum = sum+arguments[i]*arguments[i];
}
return sum;
}
var result = sumOfSquares(2,3,4)
var result2 = sumOfSquares(1,3)
console.log(result)
console.log(result2)
9 如下代碼的輸出?為什么
console.log(a);//undefined;變量a被提升
var a = 1;
console.log(b);//Uncaught ReferenceError: b is not defined;b未聲明
10. 如下代碼的輸出凤价?為什么
sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);//hello world;函數(shù)聲明被提升到代碼最前面鸽斟。
}
var sayAge = function(age){
console.log(age);//Uncaught TypeError: sayAge is not a function;這是函數(shù)表達(dá)式,只有var sayAge被提升到代碼前面利诺;
};
11. 如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
var x = 10
bar()
function foo() {
console.log(x)//10;
}
function bar(){
var x = 30
foo()
}
函數(shù)本身也是一個值富蓄,也有自己的作用域。它的作用域與變量一樣慢逾,就是其聲明時所在的作用域立倍,與其運(yùn)行時所在的作用域無關(guān)÷绿玻總之口注,函數(shù)執(zhí)行時所在的作用域,是定義時的作用域君珠,而不是調(diào)用時所在的作用域寝志。
globalContext = {
AO: {
x: 10
foo: function
bar: function
},
Scope: null
}
barContext= {
AO: {
x:30
}
scope:globalContext.AO
}
fooContex= {
AO: {}
scope:globalContext.AO
}
12. 如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
var x = 10;
bar()
function bar(){
var x = 30;
function foo(){
console.log(x) //30
}
foo();
} ```
globalContext = {
AO: {
x: 10
bar: function
},
Scope: null
}
barContext= {
AO: {
x:30
foo: function
}
scope:globalContext.AO
}
fooContex= {
AO: {}
scope:barContext.AO
}
# 13. 以下代碼輸出什么? 寫出作用域鏈的查找過程偽代碼
var x = 10;
bar()
function bar(){
var x = 30;
(function (){
console.log(x)//30
})()
}```
globalContext = {
AO: {
x: 10
bar: function
},
Scope: null
}
barContext= {
AO: {
x:30
}
scope:globalContext.AO
}
fooContex= {
AO: {}
scope:barContext.AO
}
立即執(zhí)行函數(shù)的作用域鏈 與普通函數(shù)作用域鏈一樣.(要說區(qū)別,立即不會提升)
14. 以下代碼輸出什么策添? 寫出作用域鏈查找過程偽代碼
var a = 1;
function fn(){
console.log(a)//undefined
var a = 5
console.log(a)//5
a++
var a
fn3()
fn2()
console.log(a)//20
function fn2(){
console.log(a)//6
a = 20
}
}
function fn3(){
console.log(a)//1
a = 200
}
fn()
console.log(a)//200
globalContext = {
AO: {
a: 1
fn: function
fn3: function
},
Scope: null
}
fnContext= {
AO: {
a:5
fn2: function
}
scope:globalContext.AO
}
fn2Contex= {
AO: {}
scope:fnContext.AO
}
fn3Contex= {
AO: {}
scope:globalContext.AO
}