JS函數與作用域

函數聲明和函數表達式有什么區別?

函數聲明和函數表達式是EMACScript規定的兩種不同的聲明函數的方法。
1.函數聲明

//聲明函數
function name() { //function+函數名+(參數)+{函數體} 
 console.log ('Jack')
}
//函數調用
  name()

函數聲明會在JavaScript代碼開始時提到最前面進行定義,因此函數聲明不必在調用之前定義。

2.函數表達式

var name = function () { 
   console.log ('Jack')
}

雖然變量聲明會提到JavaScript代碼開始前,但是賦值要運行到該行代碼才執行,因此在調用用函數表達式聲明的函數時,聲明必須放到調用前。

總結區別:
1.函數聲明會在代碼開始前定義,函數表達式遇到時才會執行。
2.函數聲明必須有函數名,函數表達式則可以省略。

什么是變量的聲明前置?什么是函數的聲明前置?

  • 變量的聲明前置:

在一個作用域塊中,所有的變量聲明都會被JS引擎放在作用域塊范圍的頂部進行聲明;

  • 函數的聲明前置:

和變量聲明前置一樣,執行代碼之前會先讀取函數聲明,只要函數在代碼中進行了聲明,無論它在作用域塊的哪個位置上進行聲明,JS引擎都會將它的聲明放在作用域塊范圍的頂部進行聲明;

arguments是什么?

在ECMAScript中,函數的參數在內部是用一個數組來表示的。在函數體內,可以用arguments來訪問這個參數數組。arguments是一個類數組對象(不是Array的實例),因為可以使用方括號語法訪問它的每一個元素,使用length屬性來確定傳遞進來多少參數,示例:

function test () { 
    console.log (arguments.length); //參數的長度 
    console.log (arguments[0]); //第一個參數                                                   
    console.log (arguments[1]); //第二個參數
}
test ('Jack',1,'888');
//輸出結果為 3,'Jack',1

JS函數的"重載"怎樣實現?

重載,是函數或者方法有相同的名稱,但是參數列表不相同的情形,這樣的同名不同參數的函數或者方法之間,互相稱之為重載函數或者方法。但是在JS,并沒有重載這個概念,但我們可以用另外一種方法實現這個功能:

function test (num) { 
     if (num>=90) { 
        console.log ('優秀') 
     } 
     if (num>=60&&num<90) { 
         console.log ('及格') 
      } 
     if (num<60) { 
          console.log ('不及格') 
      }
}
test(95) //輸出 '優秀'
test(77) //輸出 '及格'
test(18) //輸出 '不及格'

這樣對于同一個函數,輸入不同參數就會得到不同結果。

立即執行函數表達式是什么?有什么作用?

在JS中我們可以使用函數聲明和函數表達式聲明函數,再通過函數名進行調用:

function sayName (name) { //函數聲明聲明函數  
  console.log (name);                  
}
sayName ('Jack'); // 調用函數

var sayName = function () { //函數表達式聲明函數     
  console.log (name);
}
sayName ('Jack') // 調用函數

因為在JS中圓括號()內是不能有語句的,括號內容會被當做表達式,因此上面例子可以進行改寫:

(function (name) { 
  console.log (name);
})('Jack')
//或者
(function (name) { 
  console.log (name);
}('Jack')) // 輸出都為Jack

當JS執行到該行代碼時,函數會被定義且立即執行,叫做立即執行函數表達式。使用立即執行函數表達式可以創建一個獨立的作用域,形成隔離,避免污染全局。

求n!,用遞歸來實現

ffunction multiply(n){
    if(n===1){
        return 1;
    }
    return n*multiply(n-1);
}
multiply(3);//6

以下代碼輸出什么?

function getInfo(name, age, sex){ 
    console.log('name:',name); 
    console.log('age:', age); 
    console.log('sex:', sex); 
    console.log(arguments); //輸出整組參數; 
    arguments[0] = 'valley'; //第一個參數賦值為‘valley’
    console.log('name', name); 
}
getInfo('饑人谷', 2, '男'); 
// name:饑人谷,age:2,sex:男,['饑人谷',2,'男'],name valley;
getInfo('小谷', 3);
// name:小谷,age:3,sex:undefined,['小谷',3],name valley;
getInfo('男');
// name:男,age:undefined,sex:undefined,['男'],name valley;

寫一個函數,返回參數的平方和

function sumOfSquares(){
  var sum = 0;
  for(var i = 0;i < arguments.length; i++){
    sum += arguments[i]*arguments[i];
  }
  return sum;
}
var result = sumOfSquares(2,3,4)
var result2 = sumOfSquares(1,3)
console.log(result)  //29
console.log(result)  //10

解釋下列代碼的輸出及原因

console.log(a);  // 由于聲明提前,此時a未賦值,輸出undefined;
var a = 1;  // a=1;
console.log(b);  //報錯,b未被聲明;
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'); //調用函數,輸出'hello,world';
sayAge(10); //undefined,因為sayAge未定義;
sayAge = function(age){ 
  console.log(age);
};
//函數表達式需放到調用前!!

如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼

var x = 10
bar() 
function foo() {
  console.log(x)
}
function bar(){
  var x = 30
foo()
} // 輸出 10;

/*作用域查找過程
goblecontext = { 
  AO: { 
    X=10
    foo: function 
    bar: function 
  } 
  foo.[[scope]]: goblecontext.AO 
  bar.[[scope]]: goblecontext.AO
}
foocontext = { 
  AO: {} 
  scope: goblecontext.AO
}
barcontext = { 
  AO: { 
    x = 30 
  } 
  scope: goblecontext.AO
}*/
var x = 10;
bar() 
function bar(){
var x = 30;
function foo(){ 
console.log(x) 
}
foo();
} //輸出30
/*作用域查找過程
goblecontext = { 
  AO: { 
    x=10 
    bar:function 
  } 
  bar.[[scopr]]=goblecontext.AO
}
barcontext = { 
  AO: { 
    x=30 
    foo:function 
  } 
  foo.[[scope]]=barcontext.AO 
  scope=goblecontext.AO
}
foocontext = { 
  AO: {} 
  scope=barcontext.AO
}*/
var x = 10;
bar() 
function bar(){
var x = 30;
(function (){ 
  console.log(x)
})()
} //輸出30

/*作用域查找
goblecontext = { 
  AO: { 
    x=10 
    bar:function
  } 
  bar.[[scope]]=goblecontext.AO 
  scope=null
}
barcontext = { 
  AO: { 
    x=30 
    f:function 
  } 
  f.[[scope]]=barcontext.AO 
  scope=goblecontext.AO
}
fcontext = { 
  AO: {} 
  scope=barcontext.AO
}*/
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() //輸出:undefined,5,1,6,20,200;
console.log(a)
/*
goblecontext = {
   AO: { 
     a: undefined 
     fn: function 
     fn3: function 
   } 
   scope = null
   fn.[[scope]] = goblecontext.AO 
   fn3.[[scope]] = goblecontext.AO
}
fncontext = { 
   AO: { 
          a: undefinef 
          fn2: function 
  } 
 scope = goblecontext.AO 
 fn2.[[scope]] = fncontext.AO
}
fn2context = { 
  AO: { 
           a: 20 
  } 
  scope = fncontext.AO
}
fn3context = { 
  AO: { 
    a: 200 
   } 
  scope = goblecontext.AO
}*/
遇到fn(),開始執行:
console.log(a),,此時fncontextAO中a未被賦值,輸出undefined;
a = 5;
console.log(a),此時fncontextAO中a被賦值為5,輸出5;
a++,fncontextAO中a變為6;
var a,因為a已經存在,故無意義;
fn3(),執行fn3(),進入fn3context;
console.log(a),goblecontextAO中,a=1,故輸出1;
a=200,goblecontextAO中a變為200;
fn2,執行fn2(),進入fn2context;
console.log(a),fncontextAO中,a=6,故輸出6;
a=20,fncontextAO中,a變為20;
console.log(a),fncontextAO中,a為20,故輸出20;
fn執行完畢;
console.log(a),goblecontextAO中,a為200,故輸出200;
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 函數聲明和函數表達式有什么區別? 函數聲明和函數表達式是EMACScript規定的兩種不同的聲明函數的方法。1.函...
    LeeoZz閱讀 354評論 0 1
  • 函數聲明和函數表達式有什么區別 JavaScript 中需要創建函數的話,有兩種方法:函數聲明、函數表達式,各自寫...
    蕭雪圣閱讀 968評論 2 2
  • 1.函數聲明和函數表達式有什么區別 函數聲明 代碼執行時函數聲明會被提升到最前執行,所以函數的調用與函數聲明的順序...
    Feiyu_有貓病閱讀 402評論 0 0
  • 如題,本文介紹函數與作用域的相關知識 1.函數聲明和函數表達式有什么區別 函數聲明:使用function關鍵字可以...
    hahahahaqwert閱讀 302評論 0 0
  • 也許現在的拖延癥是最煩人的毛病了。 比如說好的減肥,一拖再拖。比如工作一拖再拖,到了deadline才會動起來,最...
    寶嫻閱讀 383評論 0 1