> 本篇文章的内容:
> 函数的属性: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。