1.函數聲明和函數表達式有什么區別
- 函數聲明使用function關鍵字進行聲明,聲明不必放到調用的前面。因為函數可以函數聲明前置。函數聲明的時候函數并沒有被執行。
- 函數表達式是將函數賦值給一個變量,聲明必須放到調用的前面。因為變量雖然也可以聲明前置,但是因為變量聲明前置的時候只是變量被前置,變量并沒有被賦值,所以聲明要放到調用前面,變量才有用。
2.什么是變量的聲明前置?什么是函數的聲明前置
- 變量的聲明前置就是將變量在變量所處的作用域內依次放在最前面進行聲明,但不賦值。聲明完之后,再依次執行JS語句。
- 函數的聲明前置同變量一樣,將函數在函數所處的作用域內依次放在最前面進行聲明,但不執行該函數。聲明完之后,再依次執行JS語句。
- 本質上變量的聲明前置和函數的聲明前置沒什么區別,都是先聲明,再使用。
3.arguments 是什么
arguments是函數的形參,它是一個類數組對象。比如:
function(name,age,sex){
name = "man";
age = 20;
arguments[2] = 1;
}
arguments[2]就是形參sex,他是函數的一個默認的形參,它可以方便的調用形參。
4.函數的"重載"怎樣實現
- JS中不存在函數的“重載”,同名函數會被覆蓋,但是JS卻可以利用函數體針對不同的參數調用相應的邏輯來達到其他語言的函數重載的效果。
- 其他語言的函數重載樣例:
function int translateNumber(parseInt(a),parseInt(b)){
statement;
}
function float translateNumber(parseFloat(a),parseFloat(b)){
statement;
}
- JS偽"重載"樣例:
function getInfOfPeople(name,age,sex) {
if(name){
console.log(name);
}
if(age){
console.log(age);
}
if(sex){
console.log(sex);
}
}
getInfOfPeople(2,3);
getInfOfPeople(2,3,1);
5.立即執行函數表達式是什么?有什么作用
- ()表示是一個表達式,而形如(function(){})()就是一個立即執行的函數表達式,他將函數禁錮在表達式內,它不會有聲明前置,而是在加載到它的時候立刻執行。
- 它的作用就是為了保護他的變量不被污染,它的變量的作用域只會在函數內。
6.求n!,用遞歸來實現
function getfactorial(n) {
if(n === 1){
return 1;
}else if(n > 1){
return n * getfactorial(n-1);
}else{
console.log("您的輸入有誤!請輸入大于1的整數");
}
}
console.log(getfactorial(5));
輸出結果120,遞歸的特點:
1.調用自身
2.有中止條件
3.算法簡單
4.效率較低
7.以下代碼輸出什么?
7.png
- 第一個getInfo()中name='饑人谷' , age=2 ,sex='男' 輸出為:
name: 饑人谷
age: 2
sex: 男
arguments[0]: "valley"
arguments[1]: 2
arguments[2]: "男"
name valley
- 第二個getInfo()中name='小谷' , age=3 輸出為:
name: 小谷
age: 3
sex: undefined
arguments[0]: "valley"
arguments[1]: 2
name valley
- 第三個getInfo()中name='男' 輸出為:
name: 男
age: undefined
sex: undefined
arguments[0]: 'valley'
name valley
8.寫一個函數,返回參數的平方和?
function sumOfSquares(){
var result =0;
for(var i=0;i<arguments.length;i++){
result += arguments[i] * arguments[i];
}
return result;
}
var result = sumOfSquares(2,3,4)
var result2 = sumOfSquares(1,3)
console.log(result) //29
console.log(result2) //10
9.如下代碼的輸出?為什么
console.log(a);
var a = 1;
console.log(b);
變量a聲明前置,但未賦值,所以console.log(a);
輸出undefined,然后變量b未聲明,所以報錯,提示變量b未被聲明。
10.如下代碼的輸出?為什么
sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
輸出hello world,sayAge() is not a function,這個考的是函數聲明和函數表達式的區別。函數聲明無需遵守順序,只要在同一作用域內,都可以被調用。而函數表達式必須放在調用之前,因為JS文檔是從上到下依次加載的,函數表達式就相當于聲明了一個變量,把函數賦值在變量內,本質上還是聲明一個變量,所以必須放在前面。sayName()是函數聲明,sayAge()是函數表達式,所以結果就是上面所說的情況。
11.如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
var x = 10
bar()
function foo() {
console.log(x)
}
function bar(){
var x = 30
foo()
}
作用域鏈偽代碼:
/*
globalContext = {
AO: {
x: 10
foo(): function(){}
bar(): function(){}
}
}
bar.[[scope]] = globalContext.AO
fooContext = {
AO: {
x: undefined
}
scope: globalContext.AO
}
barContext{
AO: {
x: 30
foo(): function(){}
}
scope: globalContext.AO
}
*/
12. 如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
var x = 10;
bar()
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
}
作用域鏈偽代碼:
/*
globalContext = {
AO: {
x: 10
bar(): function(){}
}
}
bar.[[scope]] = globalContext.AO
barContext = {
AO: {
x: 30
foo(): function(){}
}
scope: globalContext.AO
}
foo.[[scope]] = barContext.AO
fooContext = {
AO: {
x: undefined
}
scope: barContext.AO
}
*/
13.以下代碼輸出什么? 寫出作用域鏈的查找過程偽代碼
var x = 10;
bar()
function bar(){
var x = 30;
(function (){
console.log(x)
})()
}
作用域鏈偽代碼:
/*
globalContext = {
AO: {
x: 10
bar(): function(){}
}
}
bar.[[scope]] = globalContext.AO
barContext = {
AO: {
x: 30
}
scope: globalContext.AO
}
*/
14.以下代碼輸出什么? 寫出作用域鏈查找過程偽代碼
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)
作用域鏈偽代碼:
/*
globalContext = {
AO: {
a: 1
fn: function(){}
fn3: function(){}
}
}
fn.[[scope]] = globalContext.AO
fnContext = {
AO: {
a: 6
fn2(): function(){}
}
scope: globalContext.AO
}
fn2.[[scope]] = fnContext.AO
fn3.[[scope]] = fnContext.AO
fn2Context = {
AO: {
a: 20
}
scope: fnContext.AO
}
fn3Context = {
AO: {
a: 200
}
scope: globalContext.AO
}
*/