【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, ...指定的参数列表。

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

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

语法

fun.call(thisArg, [argsArray])
复制代码

参数

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

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

语法

fun.bind(thisArg[, arg1[, arg2[, ...]]])
复制代码

参数

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

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

如有侵权,请发邮箱至wk_daxiangmubu@163.com 或留言,本人会在第一时间与您联系,谢谢!!

长按二维码关注我们,了解最新前端资讯

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值