【JS第15期】Function 详解

函数实际上是一个对象。每个函数都是Function 实例,而且都与其他引用类型一样具有属性和方法。由于函数也是对象,因此函数名实际上也是一个指向函数对象的指针。

函数定义方式

函数声明

function sum(num1, num2) {
  return num1 + num2;
}

函数表达式

var sum = function(num1, num2) {
  return num1 + num2;
}

Function 构造函数

var sum = new Function('num1', 'num2', 'return num1 + num2');

注意:使用构造函数定义是不推荐的。因为这种语法会导致解析两次代码(第一次解析常规ECMAScript代码, 第二次是解析传入构造函数中的字符串),从而影响性能

函数声明与函数表达式的区别

  • 函数声明会首先被解析器读取,并使其在执行任何代码之前可以访问。如:
console.log(sum()) // 1
function sum() {
  return 1;
}
  • 函数表达式则必须等到解析器执行到它所在的代码块,才会真正被解析器执行。如:
console.log(sum()) // sum is not a function
var sum = function () {
  return 1;
}

没有重载

在创建两个同名函数时,后面的函数会覆盖了前面的函数。如:

function sum() {
  return 1;
}
function sum() {
  return 2
}
sum() // 2;

作为值的函数

因为ECMAScript 中函数名本身就是变量,所以函数可以作为值来使用。也就是说,不仅可以像传递参数一样传递给另一个参数,也可以将一个函数做为函数返回值返回,如下:

function test(func, arg) {
  return func(arg)
}
function test2() {
  return function() {
    console.log('test2')
  }
}

函数内部属性

arguments

arguments 是一个类数组的对象,返回值为函数的所有参数。这个对象还有另外一个属性callee,该属性是一个指针,指向arguments对象所在的函数的指针。举例说明:

// demo1.js
// 定义一个阶乘
function test(num){
  console.log('111')
    if(num <= 1){
        return 1;
    } else {
        return num * test(num - 1);
    }
}
test(5) // 120
// 将test函数赋值给另一个变量
var test2 = test

// 我们再重新给test定义一个方法
var test = function() {
  return 0;
}
test2(5) // 0;
test(5) // 0

再看下使用callee属性后是如何

// demo2.js
// 定义一个阶乘
function test(num){
    if(num <= 1){
        return 1;
    } else {
        return num * arguments.callee(num - 1);
    }
}
test(5) // 120
// 将test函数赋值给另一个变量
var test2 = test

// 我们再重新给test定义一个方法
var test = function() {
  return 0;
}
test2(5) // 120;
test(5) // 0

demo1.js 的代码我们为test重新定义了方法,原test变量的指向的指针发生了变化,所以返回重新定义方法的返回值。

this

this 引用的是函数执行的环境对象。但有些特殊的例外,如settimeout,setInterval等

caller

caller保存着调用当前函数的函数引用,如果是在全局作用域下调用,则返回null。如:

function outer() {
  inner()
}

function inner() {
  console.log(inner.caller)
}
outer();

以上代码为了实现松耦合,也可以通过arguments.callee.caller来访问。如:

function outer() {
  inner()
}

function inner() {
  console.log(arguments.callee.caller)
}
outer();

IE、firefox、chrome、safri 的所有版本以及opera9.6都支持caller属性。

当函数在严格模式下运行时,访问arguments.callee会导致错误。

ECMAScript 5 还定义了 arguments.caller 属性,但在严格模式下访问它也会导致错误,而在非严格模式下这个属性始终是undefined。定义arguments.callee属性是为了分清arguments.caller和函数的caller属性。以上变化为了加强这门语言的安全性,这种第三方代码不能在相同的环境里窥视其他代码了。

严格模式还有一个限制:不能为函数的caller属性赋值,否则会导致错误。

函数的属性和方法

属性

length
length属性表示函数希望接收的命名参数的个数
prototype
prototype 指向原型对象。包括诸如:toString()、valueof()等方法

方法

以下的方法都是改变函数的this指向的
call()
call() 方法调用一个函数, 其具有一个指定的this值和分别地提供的参数(参数的列表)。
语法

fun.call(thisArg, arg1, arg2, ...)
参数 描述
thisArg 在fun函数运行时指定的this值。
arg1, arg2, ... 指定的参数列表。

参数

参数 描述
thisArg 在fun函数运行时指定的this值。
arg1, arg2, ... 指定的参数列表。

返回值
返回值是你调用的方法的返回值,若该方法没有返回值,则返回undefined。
apply()

方法调用一个函数, 其具有一个指定的this值,以及作为一个数组(或类似数组的对象)提供的参数。

语法

fun.call(thisArg, [argsArray])
参数 描述
thisArg 在fun函数运行时指定的this值。
argsArray 可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。

参数

参数 描述
thisArg 在fun函数运行时指定的this值。
argsArray 可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。

返回值
调用有指定this值和参数的函数的结果。
bind()
bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。

语法

fun.bind(thisArg[, arg1[, arg2[, ...]]])
参数 描述
thisArg 当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。当使用new 操作符调用绑定函数时,该参数无效。
arg1, arg2, ... 当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。

参数

参数 描述
thisArg 当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。当使用new 操作符调用绑定函数时,该参数无效。
arg1, arg2, ... 当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。

返回值
返回由指定的this值和初始化参数改造的原函数拷贝

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352

推荐阅读更多精彩内容

  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,231评论 0 4
  • 函数和对象 1、函数 1.1 函数概述 函数对于任何一门语言来说都是核心的概念。通过函数可以封装任意多条语句,而且...
    道无虚阅读 4,556评论 0 5
  • 第3章 基本概念 3.1 语法 3.2 关键字和保留字 3.3 变量 3.4 数据类型 5种简单数据类型:Unde...
    RickCole阅读 5,118评论 0 21
  •   引用类型的值(对象)是引用类型的一个实例。   在 ECMAscript 中,引用类型是一种数据结构,用于将数...
    霜天晓阅读 1,048评论 0 1
  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,145评论 0 13