函數(shù)與作用域

函數(shù)聲明和函數(shù)表達式有什么區(qū)別

  • 函數(shù)聲明
    使用function關(guān)鍵字聲明一個函數(shù)
function sayHello {
   console.log('hello')
}
  • 函數(shù)表達式
var sayHello = function (){
   console.log('hello')
}
  • 使用函數(shù)表達式來聲明函數(shù)時,聲明必須寫在調(diào)用的前面;他們的作用域鏈不相同,函數(shù)表達式是全局作用域

什么是變量的聲明前置?什么是函數(shù)的聲明前置

代碼在電腦中編譯的過程是:
1.先檢測整段代碼中變量的聲明和函數(shù)聲明語句,執(zhí)行這些語句
2.然后按照從上到的順序執(zhí)行函數(shù)調(diào)用語句或其他語句
3.最后執(zhí)行變量的賦值
上述過程中,第一步叫做變量和函數(shù)的聲明前置

arguments 是什么

arguments對象用于獲取到該函數(shù)的所有傳入?yún)?shù),arguments對象是所有函數(shù)中可用的局部變量。可以使用arguments對象在函數(shù)中引用函數(shù)的參數(shù)。此對象包含傳遞給函數(shù)的每個參數(shù)的條目,第一個條目的索引從0開始。

函數(shù)的"重載"怎樣實現(xiàn)

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');

立即執(zhí)行函數(shù)表達式是什么?有什么作用

  • 立即執(zhí)行函數(shù)可以在函數(shù)聲明的同時立即執(zhí)行,從而隔離作用域,防止函數(shù)內(nèi)變量污染全局
(function(){
  var a  = 1;
})()
console.log(a); //undefined

其他寫法

(function fn1() {} ());
// 在數(shù)組初始化器內(nèi)只能是表達式
[function fn2() {} ()];
// 逗號也只能操作表達式
1, function fn3() {} ();
!function fn4() {} ();
(function fn5() {}) ();

求n!,用遞歸來實現(xiàn)

function factor(n){
   if(n === 1) {
     return 1
   }else if(n === 0){ 
     return 1
   }
   return n * factor(n-1)
}

以下代碼輸出什么?

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('男');

輸出:

getInfo('饑人谷', 2, '男');
getInfo('小谷', 3);
getInfo('男');
name: 饑人谷
age: 2
sex: 男
(3) ["饑人谷", 2, "男", callee: function, Symbol(Symbol.iterator): function]
name valley
name: 小谷
age: 3
sex: undefined
(2) ["小谷", 3, callee: function, Symbol(Symbol.iterator): function]
name valley
name: 男
age: undefined
sex: undefined
["男", callee: function, Symbol(Symbol.iterator): function]
name valley

寫一個函數(shù),返回參數(shù)的平方和?

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

如下代碼的輸出?為什么

console.log(a);//‘undefind’,在輸出之前 a未被賦值
var a = 1;
console.log(b);//‘Uncaught ReferenceError: b is not defined’,變量b沒有被聲明

如下代碼的輸出?為什么

sayName('world');
sayAge(10);
function sayName(name){
    console.log('hello ', name);
}
var sayAge = function(age){
    console.log(age);
};

輸出:

hello  world
Uncaught TypeError: sayAge is not a function//函數(shù)表達式不會像函數(shù)聲明一樣
被前置,所以執(zhí)行到sayAge(10);這一句時函數(shù)sayAge未被聲明,此時它還不是一個函數(shù)

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

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
   }
   Scope:bar.[[scope]] = globalContext.AO
}

fooContext = {
   AO:{}
   Scope:foo.[[scope]] = globalContext.AO
}

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

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]] = globalContext.AO
}
foo.[[scope]] = barComtext.AO

fooContext = {
   AO:{}
   Scope:foo.[[scope]] = barComtext.AO
}

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

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
   funciton
}
   Scope:bar.[[scope]] = globalContext.AO
}
function.[[scope]] = barContext.AO

functionContext = {
   AO:{}
   Scope:function.[[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()
console.log(a)

輸出:

undefine
5
1
6
20
200

作用域鏈查找過程偽代碼:

globalContext = {
   AO:{
      a:1
      fn:function
      fn3:function
   }
Scope:null
}
fn.[[scope]] = globalContext.AO

fnContext = {
   AO:{
      a:undefind
      fn3:function
      fn2:function
   }
   Scope:globalContext.AO
}
fn3.[[scope]] = fnContext.AO
fn2.[[scope]] = fnContext.AO
console.log(a)/*在a聲明之前打印,undefind*/

fnContext = {
   AO:{
      a:5
      fn3:function
      fn2:function
   }
   Scope:globalContext.AO
}
fn3.[[scope]] = fnContext.AO
fn2.[[scope]] = fnContext.AO
console.log(a)/*在fn的AO內(nèi)找a的值,此時a已被賦值5,輸出5*/

fn3Context = {
   AO:{
      a:undefined
      Scope:globalContext.AO
   }
}
console.log(a)/*在fn3的AO內(nèi)找a的值,此時a未被聲明,于是在全局Context的AO內(nèi)找
                a的值,此時a已被賦值1,輸出1*/

fn2Context = {
   a:undefined
   Scope:fnContext.AO
}
console.log(a)/*在fn2的AO內(nèi)找a的值,此時a未被聲明,于是在fn的AO中找a的值,此時
                a為6,輸出6*/

console.log(a)/*在fn2的AO內(nèi)找a的值,此時a已被賦值20,輸出20*/

console.log(a)/*a被賦值200,輸出200*/


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 函數(shù)聲明和函數(shù)表達式有什么區(qū)別 函數(shù)聲明語法:function functionName(arg0,arg1,ar...
    _Dot912閱讀 597評論 0 3
  • 1.函數(shù)聲明和函數(shù)表達式有什么區(qū)別 函數(shù)就是一段可以反復(fù)調(diào)用的代碼塊。函數(shù)還能接受輸入的參數(shù),不同的參數(shù)會返回不同...
    徐國軍_plus閱讀 501評論 0 0
  • 1.函數(shù)聲明和函數(shù)表達式有什么區(qū)別 function命令聲明的代碼區(qū)塊,就是一個函數(shù)。function命令后面是函...
    饑人谷_Leon閱讀 292評論 0 0
  • 1. 函數(shù)聲明和函數(shù)表達式有什么區(qū)別 使用function關(guān)鍵字聲明一個函數(shù)時,聲明不必放到調(diào)用的前面。//函數(shù)聲...
    _李祺閱讀 283評論 0 0
  • 資料全部來自于https://symfony.com/doc/master/components/workflow...
    vanhukset閱讀 582評論 0 0