重學前端之(4)函數、做用域、預解析

函數

爲何要有函數?

在寫代碼的時候,有一些經常使用的代碼須要書寫屢次,若是直接複製粘貼的話,會形成大量的冗餘代碼。javascript

若是修改呢?? 多個頁面呢??java

函數能夠封裝一段重複的JavaScript代碼,它只須要聲明一次,就能夠被屢次調用。面試

重複代碼、冗餘代碼的缺點:數組

  1. 代碼重複,可閱讀性差
  2. 不易維護,若是代碼邏輯改變了,全部地方的代碼都要跟着改變,效率過低。
  • 使用場景 : 只要js出現的地方都有函數函數

函數的聲明與調用

就至關於以前數組的建立和使用性能

聲明函數的語法 :ui

function 函數名() {
    // 函數體
}
複製代碼

調用函數的語法 :spa

函數名
函數名()
複製代碼

特色:代碼規範

1. 函數聲明的時候,函數體並不會執行,函數體只有在調用的時候,纔會執行;
2. 能夠調用屢次;
複製代碼

代碼示例 :code

// 聲明函數
function sayHi() {
    console.log('why');
}

// 調用函數
sayHi();
複製代碼

函數的參數

​ function getSum() {

​ var a = 10;

​ var b = 20;

​ console.log(a+b);

}

​ // 打印的是 10+20

​ getSum();

​ // 想打印 20+30? 怎麼辦????

​ getSum();

  • 形參 ( 形式參數 ) : 在函數聲明時, 設置的參數。做用是佔位置 。只能在函數內部使用.
  • 實參 ( 實際參數 ) : 在函數調用時,傳入的參數。 做用 : 函數調用時,會把實參的值賦值給形參, 這樣形參就有了值, 在函數體裏,,,能夠直接使用形參!

語法 :

//帶參數的函數聲明
function 函數名(形參1, 形參2, 形參...){
  //函數體
}

//帶參數的函數調用
函數名(實參1, 實參2, 實參3);
複製代碼

如何肯定形參:

在聲明函數的時候,碰到不肯定的值的時候,就能夠定義成形參。
複製代碼

注意:

  • 形參在聲明時,值不固定,只有在調用的時候,形參的值才肯定,形參的值會跟着函數調用時的實參不同而不同。
  • 如何肯定形參:在聲明函數的時候,碰到不肯定的值的時候,就能夠定義成形參。

函數的返回值

當函數執行完的時候,咱們指望函數給我一些反饋(好比計算的結果),這個時候可讓函數返回一些東西。也就是返回值。函數經過return返回一個返回值

返回值語法:

//聲明一個帶返回值的函數
function 函數名(形參1, 形參2, 形參...){
  //函數體
  return 返回值;
}

//能夠經過變量來接收這個返回值
var 變量 = 函數名(實參1, 實參2, 實參3);
複製代碼

函數返回值注意事項:

  • return後面的語句不執行。
  • 函數能夠沒有返回值,函數若是沒有return,那麼返回結果是undefined。
  • 函數的參數能夠有多個,可是返回值只能有1個。

函數三要素

函數三要素包括:函數名、參數、返回值

注意 : 參數和返回值能夠沒有,,,可是函數名必定要有;


`

函數內部能夠調用函數-1

在函數內部是能夠繼續調用別的函數的。

function chiFan() {

      console.log('開始吃飯');
      console.log('吃完了');
    }
    function qiaoDaiMa() {

      console.log('開始敲代碼');
      chiFan()
      console.log('代碼敲完了');
    }
    qiaoDaiMa()
複製代碼

函數內部能夠調用函數-2

遞歸函數

遞歸函數:本身直接或者間接調用本身的函數;

注意 : 遞歸函數必定要留有出口,否則就是死循環了


練習:

// 1. 求1-100全部數的和 (使用遞歸)
 2. 斐波那契數列,有我的想知道,一年以內一對兔子能繁殖多少對?因而就築了一道圍牆把一對兔子關在裏面。已知一對兔子每月能夠生一對小兔子,而一對兔子從出生後第3個月起每個月生一對小兔子。假如一年內沒有發生死亡現象,那麼,一對兔子一年內(12個月)能繁殖成多少對?
  //兔子的規律爲數列,1,1,2,3,5,8,13,21 ,34 , 55, 89, 144
複製代碼

場景 : 少用,,性能也不太好! 100個月

函數也是一種類型

聲明函數的兩種方式

方式1 : 函數聲明:

function 函數名(){
  //函數體
}
複製代碼

方式2 : 函數表達式 ( 匿名函數 )

var 函數名 = function(){
  //函數體
}
複製代碼

函數能夠做爲參數

一般,咱們把做爲參數傳遞的函數叫作回調函數

function fn1(fn) {
  fn();
}
fn1(function(){
   console.log("哈哈"); 
});
複製代碼

函數能夠做爲返回值

function fn1() {
    return function(){
      console.log("呵呵");
    }
}
fn1()();//調用
複製代碼

做用域

做用域:變量起做用的區域

全局做用域 :在script標籤內,函數外的區域就是全局做用域,在全局做用內聲明的變量叫作全局變量 。全局變量能夠在任意地方訪問。

函數做用域 :在 函數內的區域 叫作函數做用域,在函數做用域內聲明的變量叫作局部變量 ,局部變量只有在當前函數內才能訪問到。

全局變量:在函數外,script標籤內聲明的變量就是全局變量,全局變量在任何地方都能訪問的到。

局部變量:在函數中聲明的變量,就是局部變量,局部變量只有在當前函數體內可以訪問。

隱式全局變量:沒有使用var定義的變量也是全局變量,叫作隱式全局變量。(不要使用)

總結 :

// 全局做用域 : script標籤內, 函數外 
// 全局變量 => 任何地方均可以訪問
// 函數做用域 : 函數內部 
// 局部變量 => `當前函數`內部

// 除了兩個經常使用的變量還有 隱式全局變量 : 任何地方都能訪問(前提是已經好) (避免使用)(先執行函數)
複製代碼
// 查看哪些是全局、局部、隱式全局
// 計算
 var num = 11;

function fn() {
    var num1 = 12;
    num2 = 22;
    console.log(num);
    console.log(num1);
}
fn();
console.log(num);
// console.log(num1);
console.log(num2);
複製代碼

變量的查找規則:

  • 函數內部可使用函數外部的變量 (見上例)

  • 有局部變量就用局部變量,沒有局部變量就用全局變量。 (見下例)


demo :

var num = 11;
function fn() {
  var num = 22;
  console.log(num);//22
}
fn();
console.log(num);//11
複製代碼

demo :

//1. 
 var num = 11; //全局
   function fn() {
     num = 44; //全局
     console.log(num);
   }
   fn();
   console.log(num);
   // 總結 : 函數內部能夠訪問函數外部的變量 ,反之不能夠

//2.
   var num1 = 11; //全局
   var num2 = 22; //全局
   function fn() {
     var num1 = 33; //局部
     num1 = 44;
     num2 = 55;
     console.log(num1);
     console.log(num2);
   }
   fn();
  // 總結 : 有局部就優先用局部
   console.log(num1);
   console.log(num2);

//3.
  var num1 = 11; //全局
  function fn() {
    var num1 = 22; //局部
    num1 = 33; //局部
    num2 = 44; //隱式全局
    console.log(num1); 
    console.log(num2);
  }
  fn();
  console.log(num1);
  console.log(num2);
複製代碼

預解析

​ console.log(num4);

​ // var num4 = '123';

js執行代碼分爲兩個過程:

  • 預解析過程(變量與函數提高)
  • 代碼一行一行執行

預解析過程:分別舉例

// 預解析過程
// 1. 把var聲明的變量提高到當前做用域最前面,不會提高賦值 
// 2. 把函數聲明 提高到當前做用域的最前面,,
// 3. 若是函數同名 ??? 後者會覆蓋前者 
// 4. 若是 var聲明的 和 函數聲明的同名 , 函數優先
複製代碼

面試題:

//1. 
var num = 10;
fn1();
function fn1() {
  console.log(num);
  var num = 20;
}

//2. 
var a = 18;
fn2();
function fn2() {
    var b = 9;
    console.log(a);
    console.log(b);
}

//3.
fn3();
console.log(c);
console.log(b);
console.log(a);
function fn3() {
  var a = b = c = 9;
  console.log(a);
  console.log(b);
  console.log(c);
}

//4. 思考題
var a = 4;
    console.log(a);
    a = 6;
    console.log(a);
    function a() {
      console.log('哈');
    }

    a();

    a = 10;
    console.log(a);

複製代碼

匿名函數與自執行函數

匿名函數

匿名函數:沒有名字的函數

匿名函數如何使用:

1. 將匿名函數賦值給一個變量,這樣就能夠經過變量進行調用
2. 自執行(匿名函數自執行)
複製代碼

匿名函數自執行的做用:防止全局變量污染。

// 自執行
(function fn(){
  console.log("我能夠本身執行哦");
})();

//張三的代碼
  ;(function(){
    var num = 11;
    function fn() {
      console.log("呵呵")
    }
    fn();
    console.log(num);
  })();
//李四的代碼

注意: 分號
複製代碼

// 注意點 : 代碼規範

var a = 10
    var b = 20
    b = a
    (function () {

      console.log(b);

    })();
複製代碼
相關文章
相關標籤/搜索