javascript函数篇四、函数的属性和方法——apply()、call()和bind()方法区别

> 本篇文章的内容:
> 函数的属性:length、prototypy、caller;
> 函数的方法: apply()、call()、bind()

因为在javascript中函数也是对象,所以函数也有属性和方法。每个函数都包含三个属性。

length

function fn (n1, n2) {
    return n1 + n2
}
console.log(fn.length) // 2

**length属性表示函数希望接收的函数个数。**

prototypy
每一个函数都有一个prototype属性,它是一个对象,prototype是一个极其重要的属性,这里只做一个简单罗列,以后会详细介绍。

caller
ECMAScript5还规范化了一个函数对象的属性,就是caller,它指向的是调用当前函数的函数的引用,如果是在全局作用域中调用当前函数,它的值为null。

function a () {
    b()
}
function b () {
    console.log(b.caller) // 打印a函数的源代码
}
a()

注意当函数在严格模式下执行的时候会导致错误!

每个函数都包含两个方法:apply()和call(),另外在ECMAScript5中还定义了一个方法bind()。下面来介绍这三个方法。

apply()、call()、bind()
1、apply()和call()
首先apply()和call()的作用都是改变函数执行的上下文,也就是this值。每个函数都有这两个方法,它们的第一个参数都是你要指定的上下文,第二参数就是传递的参数。

var obj = {
    a: 1
}
function add (b, c) {
    return this.a + b + c
}
console.log(add.apply(obj, [1, 2])) // 4
console.log(add.call(obj, 3, 4)) // 8

apply()和call()两种方法的区别仅仅在于传参方式,apply要以数组的形式传参,call则需要一一传入。

2、与call和apply不同,bind()不会立即执行
***bind()在使用的时候,调用bind()方法的函数不会立即执行,而是返回一个改变了上下文的函数副本(即重新创建了一个函数,然后将this指向bind函数的第一个参数,最后将这个新创建的函数返回)***

bind()方法是如何实现的呢?为了更好的理解bind方法我们来模拟一下bind方法的实现:

if (!function(){}.bind) { // 如果没有bind方法则向Function对象的原型中添加自定义的bind方法,因为有的浏览器(如ie6~ie8)并不支持bind,所以若想在多个浏览器中使用bind可以这样做兼容处理
    Function.prototype.bind = function(cnt) {
        var fn = this // 获取调用bind方法的函数
        var args = Array.prototype.slice.call(arguments) // 这里是将bind方法内的arguments对象转为数组,以便arguments能使用数组的方法
            return function () { //返回一个函数, 而这个函数的内部是执行调用bind()的函数,并将执行的结果返回
                return fn.apply(cnt, args.slice(1))
            }
       }
}    

通过模拟bind()可以清晰的看到bind方法的实现原理,为了好理解假设有如下调用:fn.bind(obj, a, b):
在bind函数的内部是这样操作的,首先通过this拿到调用bind方法的函数fn利用arguments对象处理传入bind方法的参数,拿到除第一个参数以外的参数(这里的a,b)。整个bind方法返回一个函数,函数内部执行调用bind方法的函数fn,并利用apply方法将fn的this指向传入bind函数的第一参数(obj),并将fn执行结果返回

利用bind()方法不会立即执行的特点,我们可以在一些交互的时间处理函数中使用bind()。

var btn = document.getElementById("btn")
var lines = document.getElementById("lines")
btn.onclick = function() {
    console.log(this.id) // lines
}.bind(lines) // 此时处理函数不会立即执行,当点击事件触发时,bind()返回的函数副本执行,返回了fn.apply(cnt, args.slice(1)); apply立即执行

调用了bind方法的点击事件处理函数不会立即执行,当点击事件触发时,bind()返回的函数副本执行,这时候返回了fn.apply(cnt, args.slice(1)); apply立即执行处理函数,同时改变了this指向,输出结果为lines。

原文地址:https://www.cnblogs.com/youyang-2018/p/11706522.html