JS里的函數(shù)

函數(shù)

函數(shù), function, 是一個(gè)關(guān)鍵字, 表示聲明一個(gè)函數(shù), 是一個(gè)變量的特例.

每一個(gè)函數(shù),都必須有一個(gè)return, 如果不寫return, 默認(rèn)會(huì)添加return undefined.

函數(shù)本質(zhì)

函數(shù)就是將做一件相同事情的代碼整合到一起,作為代碼塊, 可以被反復(fù)調(diào)用,可以執(zhí)行代碼的對(duì)象就是函數(shù).

函數(shù)的五種聲明方式

  1. 具名函數(shù)
function x(input1, input2){ return }
  1. 匿名函數(shù)
var x = function(input1, input2){ return }
// 匿名函數(shù)必須給一個(gè)變量
  1. 具名函數(shù)賦值
var x = function y(input1, input2){ return }
  1. Window.function
var x = new Function('x', 'y', 'return x + y')
  1. 箭頭函數(shù)
var x = (x, y) => { return x + y}
var x = (x, y) => { let n = x * 3; let m = y * 4; return n + m;}

具名函數(shù)和具名函數(shù)賦值兩種聲明的區(qū)別:

不一致性, 作用域不同, 垃圾特性.

分別聲明具名函數(shù)和具名函數(shù)賦值, 并console.log(函數(shù)):

image
image

console.log()原理

console.log = function(a){
    alert(a)
    return undefined
}
// 由此可見(jiàn), console.log 永遠(yuǎn)返回undefined, 返回什么和打印什么 一點(diǎn)關(guān)系沒(méi)有

函數(shù)的name屬性

var f2 = function(){}
f2.name = "f2";

var f3 = function f4(){}
f3.name = "f4"

var f5 = new Function('x','y','return x + y')
f5.name = "anonymous" // 匿名的意思

如何調(diào)用函數(shù)

function f(x,y){ return x + y }

f(1,2) // 3

// 骨灰級(jí)寫法, 真正的函數(shù)調(diào)用
f.call(undefined, 1, 2)

call()原理:

var f = new Function('x','y','console.log(1)')
f.call() // 1
// Function構(gòu)造函數(shù), 除了最后一個(gè)參數(shù)是函數(shù)體, 其他的都是參數(shù)
// 分解如下
var f = {};
f.parmas = ['x','y'];
f.functionBody = 'console.log(1)';
f.call = function(){
    window.eval(f.functionBody)
}
f.call() // 1

由上可得出: 為什么說(shuō)函數(shù)是對(duì)象, 因?yàn)檎{(diào)用的過(guò)程就是執(zhí)行eval函數(shù)體的過(guò)程, 可以執(zhí)行代碼的對(duì)象就是函數(shù)

f和f.call()的區(qū)別:

f 是對(duì)象, f.call 是執(zhí)行對(duì)象的函數(shù)體

this 和 arguments

call()的第一個(gè)參數(shù)可以用this得到.后面的參數(shù)可以用arguments得到.

  • this

上述代碼中f.call(undefined, 1, 2), undefined就是this, 當(dāng)時(shí)要求JS必須長(zhǎng)的像java, 所有強(qiáng)行加了this

  • arguments

上述代碼中f.call(undefined, 1, 2), [1,2]就是arguments.

image
  • arguments也是一個(gè)偽數(shù)組, 因?yàn)殚L(zhǎng)的像數(shù)組, 原型鏈中沒(méi)有Array.prototype, 或者是____proto____沒(méi)有指向Array.prototype.
function f(){
    console.log(this)
}
f.call(1) // Number 對(duì)象 1


function f(){
    'use strict' // 嚴(yán)格模式
    console.log(this)
}
f.call(1) // 1

作用域

作用域(scope)指的是變量存在的范圍。在 ES5 的規(guī)范中,Javascript 只有兩種作用域:一種是全局作用域,變量在整個(gè)程序中一直存在,所有地方都可以讀?。涣硪环N是函數(shù)作用域,變量只在函數(shù)內(nèi)部存在.只要有函數(shù)就有作用域

作用域?qū)?yīng)的數(shù)據(jù)結(jié)構(gòu)是樹(shù):

var a = 1;
function f(){
    console.log(a)
    var a = 2;
   
    function f2(){
        console.log(a)
    }
}
function f1(){
    var a = 3;
    console.log(a)
}

console.log(a)
f()

// 代碼作用域如下圖:
image.png
  • 函數(shù)外部聲明的變量就是全局變量(global variable),它可以在函數(shù)內(nèi)部讀取。

  • 在函數(shù)內(nèi)部定義的變量,外部無(wú)法讀取,稱為“局部變量”(local variable)。

函數(shù)內(nèi)部的變量提升

與全局作用域一樣,函數(shù)作用域內(nèi)部也會(huì)產(chǎn)生“變量提升”現(xiàn)象。var命令聲明的變量,不管在什么位置,變量聲明都會(huì)被提升到函數(shù)體的頭部。

function f(){
    console.log(a);
    var a = 1;
}

// 等同于
function f(){
    var a;
    console.log(a);
    var a = 1;
}

// a 打印出undefined

函數(shù)本身的作用域

函數(shù)本身也是一個(gè)值,也有自己的作用域。它的作用域與變量一樣,就是其聲明時(shí)所在的作用域,與其運(yùn)行時(shí)所在的作用域無(wú)關(guān)。

var a = 1;
function x(){
    console.log(a);
}

function f(){
    var a = 2;
    x();
}
f(); // 1

// 等同于
var a;
a = 1;
function x(){
    console.log(a); // 1
}

function f(){
    var a;
    a = 2;
    x();
}
f();

上面代碼中,函數(shù)x是在函數(shù)f的外部聲明的,所以它的作用域綁定外層,內(nèi)部變量a不會(huì)到函數(shù)f體內(nèi)取值,所以輸出1,而不是2

總之,函數(shù)執(zhí)行時(shí)所在的作用域,是定義時(shí)的作用域,而不是調(diào)用時(shí)所在的作用域.

閉包

如果一個(gè)函數(shù), 使用了它范圍外的值, 那么(這個(gè)函數(shù)+這個(gè)變量)就叫做閉包.

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容