call / apply
- fn.call(asThis, p1,p2) 是函数的正常调用方式
当你不确定参数的个数时,就使用 apply
fn.apply(asThis, params)
bind
-
call 和 apply 是直接调用函数,而 bind 则是返回一个新函数(并没有调用原来的函数),这个新函数会 call 原来的函数,call 的参数由你指定。
-
举个例子,一个简单的点击事件,当element被点击后调用onClick方法。onclick函数被浏览器调用时他的this就是触发事件的元素,也就是代码中的div1,但onClick方法的this必须指向view,所以我们通常用提前声明_this或that来保存this,防止this不明确。
1 2 3 4 5 6 7 8 9 10 11 12 13
| var view = { element: $('#div1') bindEvents: function() { var _this = this this.element.onclick = function() { _this.onClick.call(_this) } }, onClick: function() { this.element.addClass('active') } }
|
- 通过bind我们可以解决以上问题,直接用bind返回一个新的函数,新函数call原来函数,this和参数可以自己指定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var view = { element: $('#div1') bindEvents: function() {
this.element.onClick = this.onClick.bind(this) }, onClick: function() { this.element.addClass('active') } }
|
柯里化 / 高阶函数
柯里化:返回函数的函数
将 f(x,y) 变成 f(x=1)(y) 或 f(y=1)x
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function sum(x,y){ return x+y }
function addOne(y){ return sum(1, y) }
function Handlebar(template, data){ return template.replace('{{name}}', data.name) }
function Handlebar(template){ return function(data){ return template.replace('{{name}}', data.name) } }
|
- 柯里化可以将真实计算拖延到最后再做
- 关于柯里化的高级文章:
高阶函数:
- 在数学和计算机科学中,高阶函数是至少满足下列一个条件的函数:
- 接受一个或多个函数作为输入:forEach sort map filter reduce
- 输出一个函数:lodash.curry
- 不过它也可以同时满足两个条件:Function.prototype.bind
作用:可以将多个函数组合成一个新函数,功能更强大。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
array = [1,2,3,4,5,6,7,8]
var sum = 0 for(var i = 0;i < array.length;i++) { if(array[i] % 2 === 0) { sum += array[i] } return sum }
array.filter.call(array, function(n){return n%2===0}).reduce(function(prev, next){return prev+next}, 0)
array.reduce.call(array.filter(function(n){return n%2===0}),function(prev, next){return prev+next}, 0)
|
回调
- 名词形式:被当做参数的函数就是回调
- 动词形式:调用这个回调
构造函数
箭头函数
- 使用箭头函数的好处就是箭头函数的参数没有this,它无法指定this的值,你可以根据词法作用域知道this的值。箭头函数参数就是arguments,你传入一个参数,它会自己return结果,写法非常直观。这样我们不需要关系this有没有改变,因为箭头函数不会改变this的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| setTimeout(function(a) { console.log(this) setTimeout(function(a){ console.log(this) }, 1000) }.bind({name:'tutu'}), 1000)
setTimeout(function(a) { console.log(this) setTimeout(function(a){ console.log(this) }.bind({name:'tutu'}), 1000) }.bind({name:'tutu'}), 1000)
setTimeout(function(a) { console.log(this) setTimeout((a) => {console.log(this)}, 1000) }.bind({name:'tutu'}), 1000)
|
用柯里化实现下面函数功能,这个函数能够将接受多个参数的函数,变成多个接受一个参数的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| function curry(???){ ??? return ??? }
var abc = function(a, b, c) { return [a, b, c]; };
var curried = curry(abc);
curried(1)(2)(3);
curried(1, 2)(3);
curried(1, 2, 3);
function curry(func , fixedParams){ if ( !Array.isArray(fixedParams) ) { fixedParams = [ ] } return function(){ let newParams = Array.prototype.slice.call(arguments); if ( (fixedParams.length+newParams.length) < func.length ) { return curry(func , fixedParams.concat(newParams)); }else{ return func.apply(undefined, fixedParams.concat(newParams)); } } }
|