重新认识了一下函数
函数的三种角色
一些函数作为对象的属性
length:形参的个数;name:函数名;prototype:类的原型,在原型上定义的方法都是当前这个类的实例的公有方法;__proto__:把函数当做一个普通对象,指向Function这个类的原型
函数的角色
- 普通函数。它本身是一个普通的函数,执行的时候会形成私有的作用域,然后进行形参赋值、预解析、代码执行、执行完成后内存销毁;
- 类。有自己的实例,也有一个叫做
prototype的属性是自己的原型,它的实例都可以指向自己的原型; - 普通对象。它作为对象可以有一些自己的私有属性,也可以通过
__proto__找到Function.prototype;

call方法原理
1 | function sum(){ |
一个经典栗子(需要深入理解call原理和原型链)
1 | function fn1() { |
第二个输出有了前面的基础就很好理解了。前面了解到函数可以作为普通对象,然后有原型链搜索这一过程。
1 | fn2 { |
第二次的call将fn1.call这个函数的this绑定到fn2上(将fn2作为普通对象),再将fn1.call重新执行,此时,fn1.call函数里面的this就指向了fn2这个对象了,所以不是重新执行fn1(),而是重新执行fn2()。
思考
1 | Array.prototype.slice.call(arguments) || [].slice.call(arguments) |
这个方法用于将类数组对象转化为数组。
call、apply、bind的区别
call和apply基本一样,就是传递参数形式不一样
1 | function fn(num1, num2) { |
bind有点不一样,它会返回函数,而不是立即执行
1 | var tempFn = fn.bind(obj, 1, 2); |
补充一下ES5的严格模式
1 | -- 严格模式 |
apply和call的实现基本一样,就是处理arguments不一样。
1 | if(arguments[1]) { |
自己实现一个bind
1 | function myBind() { |
Function.apply.bind
看一个js的高级技巧
1 | Promise.resolve([10,20]).then(Function.apply.bind(function(x, y){ |
先不管Promise
1 | var sum = function(x, y) { |
sum.apply(null, [10, 20])很好理解,bind(sum)使Function.apply这个函数里面的this指向了sum这个函数对象,所以Function.apply.bind(sum, null)等价于sum.apply.bind(sum, null),bind的使命已经完成了。所以就等价于sum.apply。
Function.bind.apply
1 | Function.bind.apply(sum, null) |
原理一样的。等价于sum.bind(sum, null),就等价于sum
看起来很简单,其实还是有很多东西的,哈哈,是不是感觉收获颇丰啊,不用谢了啦。