JS深入淺出Function與構造函數

 1.概述

Function是一個構造函數,可以通過該構造函數去創建一個函數,創建的函數是一個Function對象,實際上,不管使用什麼方式創建的都是一個Function對象,本質上函數名僅僅是一個變量名,它指向某個Function對象的引用。

驗證代碼如下所示:

var f = function () {
  console.log('this is f function');
}
// 函數也是一個對象
console.log(f instanceof Object); // true
// 函數是Function類型的對象
console.log(f instanceof Function); // true

1.1利用Function構造函數創建函數

Function****構造函數創建一個新的Function對象。直接調用此構造函數可用動態創建函數。

語法結構如下:

var functionName = new Function ([arg1[, arg2[, ...argN]],] functionBody)


其中functionName表示函數名稱,[arg1[, arg2[, …argN]],]表示可選的參數列表,functionBody表示函數

示例代碼如下所示:

// 無參的函數
var fun = new Function('console.log("這是一個函數")')
fun() // 這是一個函數
// 帶一個參數的函數
var fun = new Function('a', 'console.log("這個函數帶一個參數:" + a)')
fun(100) // 這個函數帶一個參數:100
// 帶兩個參數的函數
var fun = new Function(
  'a, b',
  'console.log("這是帶兩個參數的函數,分別是" + a + "和" + b);',
)
fun(100, 200) // 這是帶兩個參數的函數,分別是100和200

在實際的開發中我們一般不使用這種方式創建函數,因為它毫無可讀性。

1.2Function與Object

  • Object類型和Function是JavaScript中的引用類型之一
  • 構造函數也是函數的一種
  • 函數其實是一個Function類型的對象
  • JavaScript中所有對象都是Object類型的

驗證代碼如下:

console.log(Function instanceof Function) //true
console.log(Function instanceof Object) //true
console.log(Object instanceof Object) //true
console.log(Object instanceof Function) //true

2.構造函數

2.1自定義否則函數

構造函數又稱為構造器或對象模板,是對象中的一個方法,在實例化時構造器被調用。在JavaScript中函數就可以作為構造器使用,因此不需要特別定義一個構造器方法。

創建構造函數的語法結構如下所示:

function Person(){
  this.屬性名 = 屬性值;
  this.方法名 = function() {
      方法體
}
var person = new Person();


這裡的Person是作為構造函數的名稱,將Person實例化需要使用new關鍵字,還有一點需要說的就是構造函數一般首字母都是大寫的。

如下代碼展示瞭如何通過創建一個構造函數以及如何通過構造函數去實例化一個類:

// 自定義構造函數 -> 作用:創建對象
function Person(name, age, sex) {
  this.name = name
  this.age = age
  this.sex = sex
  this.print = function () {
    console.log(name + '今年' + age + '歲 性別' + sex)
  }
}
// 創建 一碗甜
var t = new Person('一碗甜', 18, '女')
hong.print() // 一碗甜今年18歲 性別女
// 創建 一碗周
var z = new Person('一碗周', 20, '男')
dong.print() //一碗粥今年20歲 性別男

2.2對象的constructor屬性

Object對象提供的constructor屬性,返回創建實例對象Object的構造函數的引用。

所有對象都會從它的原型上繼承一個constructor屬性:

值得註意的是此屬性的值是對函數本身的引用,而不是一個包含函數名稱的字符串。

示例代碼如下:

// 創建 一碗周
var z = new Person('一碗周', 18, '男')
// 判斷是否為 Person 構造函數的對象
console.log(z.constructor === Person)

2.3構造函數與函數

先看一段代碼

function Hero() {
  // 當作是一個函數來使用
  var v = 100 // 局部變量
  // 當作是一個構造函數來使用
  this.set = function (value) {
    v = value
  }
  this.get = function () {
    return v
  }
}


在這段代碼中,首先我們定義瞭一個函數,那它也是一個構造函數,當然它還是一個對象。

既然它有三個方面的含義,那就有三個方面的操作,如下所示

  • 直接當做函數調用
  • 通過構造函數創建對象
  • 當做對象為其添加屬性或者方法

示例代碼代碼如下:

// 直接調用
Hero()
// 通過構造函數創建對象
var hero = new Hero()
// 當做對象為其添加屬性和方法
Hero.n = '一碗周'
console.log(Hero.n) // 一碗周

3.Function對象的屬性和方法

全局的Function對象沒有自己的屬性和方法,但是,因為它本身也是一個函數,所以它也會通過原型鏈從自己的原型鏈Function.prototype上繼承一些屬性和方法。

3.1length屬性

length屬性指明函數的形參個數,示例代碼如下所示:

// 定義兩個空函數
function fun(a, b, c, d) {}

function fn() {}

// 測試 length 屬性
console.log(fun.length) // 4
console.log(fn.length) // 0

apply()方法:

**apply()**方法調用一個具有給定this值的函數,以及以一個數組(或類數組對象)的形式提供的參數。

法格式如下:

func.apply(thisArg, [argsArray])


參數解釋如下:

  • thisArg:必選的。在func函數運行時使用的this值。請註意,this可能不是該方法看到的實際值:如果這個函數處於非嚴格模式下,則指定為null或undefined時會自動替換為指向全局對象,原始值會被包裝。
  • argsArray:可選的。一個數組或者類數組對象,其中的數組元素將作為單獨的參數傳給func函數。如果該參數的值為null或undefined,則表示不需要傳入任何參數。從ECMAScript5開始可以使用類數組對象。

返回值是調用有指定this值和參數的函數的結果。

如下代碼展示瞭apply()方法的用法:

// 定義一個函數
function fn(a) {
  console.log('this is ' + a)
}
fn.apply(null, ['函數']) // this is 函數

// 上面的調用方式等同於下面這種方式
fn('函數') // this is 函數

3.2call()方法

該方法的語法和作用與apply()方法類似,隻有一個區別,就是call()方法接受的是一個參數列表,而apply()方法接受的是一個包含多個參數的數組。

如下代碼展示瞭call()方法的用法:

function fn(a) {
  console.log('this is ' + a)
}
fn.call(null, '函數') // this is 函數

// 上面的調用方式等同於下面這種方式
fn('函數') // this is 函數

bind()方法:
ind()方法創建一個新的函數,在bind()被調用時,這個新函數的this被指定為bind()的第一個參數,而其餘參數將作為新函數的參數,供調用時使用。

參數解釋如下:

function.bind(thisArg[, arg1[, arg2[, ...]]])

參數:

thisArg:調用綁定函數時作為this參數傳遞給目標函數的值。

arg1, arg2, …:當目標函數被調用時,被預置入綁定函數的參數列表中的參數。

返回值是一個原函數的拷貝,並擁有指定的**this**值和初始參數。

如下代碼展示瞭bind()方法的:

// 定義一個函數
var fun = function (a, b) {
  console.log('第一個參數的值為:' + a + '第二個參數的值為:' + b)
}
// 調用 fun()
fun(10, 20) // 第一個參數的值為:10第二個參數的值為:20
// 創建綁定函數
var fn = fun.bind(null, 100, 200) // 有參數默認值的功能
// 調用新創建的函數,不寫實參
fn() // 第一個參數的值為:100第二個參數的值為:200

4.Arguments對象

arguments對象是所有(非箭頭)函數中都可用的局部變量。你可以使用arguments對象在函數中引用函數的參數。此對象包含傳遞給函數的每個參數,第一個參數在索引0處。例如,如果一個函數傳遞瞭三個參數,你可以以如下方式引用他們:

arguments[0]
arguments[1]
arguments[2]

它的參數也是可以被重新定義的,該對象還提供瞭兩個屬性,分別是:

  • arguments.length:返回傳遞給函數的參數數量
  • arguments.callee :返回指向參數所屬的當前執行的函數。如果這個屬性後面緊跟一個 (),則表示調用此函數,因為arguments.callee === fun的結果為 true

如下代碼展示瞭該對象的用法,代碼如下:

/*
 * arguments 對象是一個存在於函數體中的特殊對象。
 * arguments 對象是一個類數組對象
 * arguments 對象對應傳遞給函數的實參
 */
// 定義一個函數
var fun = function () {
  console.log(arguments)
  // arguments.callee  指向參數所屬的當前執行的函數。
  //如果給這個屬性加一個括號則表示調用。因為 arguments.callee === fun 的結果為 true
  console.log(arguments.callee)
  // arguments.length  傳遞給函數的參數數量。
  console.log(arguments.length)
}
fun(1, 2, 3, 4, 5) 


代碼執行結果如下所示:

[Arguments] { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }
[Function: fun]
5


我們可以通過arguments.length屬性,來判斷傳入參數的數量,來完成函數重載的功能,示例代碼如下:

// 模擬函數的重載
function add() {
  // 記錄參數數量
  var len = arguments.length
  // 通過 switch case 語句判斷傳入參數數量,來模擬重載的功能
  switch (len) {
    case 2:
      return arguments[0] + arguments[1]
      break
    case 3:
      return arguments[0] + arguments[1] + arguments[2]
      break
    case 4:
      return arguments[0] + arguments[1] + arguments[2] + arguments[3]
      break

    default:
      break
  }
}
console.log(add(1, 2)) // 3
console.log(add(1, 2, 3)) // 6
console.log(add(1, 2, 3, 4)) // 10

5.總結

本篇文章介紹瞭如何創建構造函數,如何通過構造函數去實例化一個對象;以及Function對象提供的方法和屬性有哪些?怎麼用,最後還介紹瞭一個Arguments對象。

到此這篇關於JS深入淺出Function與構造函數的文章就介紹到這瞭,更多相關JS unction與構造函數內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: