javascript - 关于apply()与call()的问题
滿天的星座
滿天的星座 2017-07-05 11:01:57
0
5
1189
function sum(num1,num2) {
    return num1 + num2;
}
function callSum1(num1,num2) {
    return sum.apply(this,arguments);
}
function callSum2(num1,num2) {
    return sum.apply(this,[num1,num2]);
}

alert(callSum1(10,10));
alert(callSum2(10,10));

//call()例子就省略了

问:
1.sum.apply(this,arguments)说的是对象sum调用apply方法,this指的是callSum()与sum()都是同一个作用域运行,arguments指的就是”sum1,sum2”?
2.apply()与call()的在项目中应用价值是什么呢?

滿天的星座
滿天的星座

全部回复(5)
淡淡烟草味

楼上写的真复杂:)

听我讲讲,题主疑惑的地方
1:

function callSum1(num1,num2) {
    return sum.apply(this,arguments);    // 这里的arguments和下面的[num1,num2]是同一个意思
}
function callSum2(num1,num2) {
    return sum.apply(this,[num1,num2]);
}

arguments 是一个类似数组的对象, 对应于传递给函数的参数。arguments对象是所有函数中可用的局部变量。你可以使用arguments对象在函数中引用函数的参数。

PS:this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象

2、call和apply应用价值(存在的意义):

作用都是为了改变函数运行时上下文而存在的。 即改变函数体内部this的指向
"说白点,a有xx方法,b没有。b可以问a借!"(这tm不就是继承嘛~)

call和apply不同点:

接受参数方式不一样。

如下:
call接受的是连续参数,apply接受的是数组参数。
A.call(this, a,b,c,d)
A.apply(this, [a,b,c,d])

一个传送门:http://www.jianshu.com/p/a7b1...

typecho
  1. arguments是function内置属性之一,表示函数数组对象,即 callSum1里的arguments 指代 num1和num2
    https://developer.mozilla.org...

  2. apply 跟 call的价值在于,能够使得指定函数里面的this指向特定的对象上,举个例子,我们用document.querySelectorAll()获取的dom其实是一个类数组对象,非数组,如果想要用数组的方法时,可以是这样

var doms = document.querySelectorAll('p');
[].forEach.call(doms, function(e){
    //遍历元素
});

而apply 跟call主要区别在于参数格式,这个建议题主翻翻MDN。

巴扎黑

1.sum.apply(this,arguments)说的是对象sum调用apply方法,this指的是callSum()与sum()都是同一个作用域运行,arguments指的就是”sum1,sum2”?

2.apply()与call()的在项目中应用价值是什么呢?

针对 1 执行结果两个都返回 20 20

sum.apply(this,arguments) 指的是用apply来调用sum 指定sum执行的时候的this为现在的这个this 后面的arguments是参数列表 是一个类数组对象,你可以简单地当成数组对待。

sum.apply(this,[num1, num2]) 与上面类似。

关于arguments,发一张截图你可能就会有感性的认识了


以下是针对第二点的回答

钦点this

比较好理解 就是改变 this 指向 比如在 ajax 请求的 success 回调的时候

比如在vue开发的时候 如果没有箭头函数 得要用 var that = this 这样暂存 this。 如果可以钦点this就没这些问题

举个栗子

function sayName(){
    console.log(this.name); 
}

var xiao_ming = {
    name: '小明妹妹'
}

// 钦点 this 
sayName.call(xiao_ming); 

把类数组对象转化成真丶数组

arguments 通过类数组对象的形式 保存着函数的参数列表 。

function sumAll(){
    var argu = Array.prototype.slice.call(arguments); 
    
    // 从 0 开始积、每次 sum + cur 作为下次的 sum 
    return argu.reduce((sum, cur) => sum + cur, 0); 
}

其实从这里可以窥见:执行 slice 只需要对象具备 length 正确的下标 就可以正常执行 并返回结果。

因为数组的很多方法都可以用在类数组对象上,因此类数组对象很多时候确实可以被认为就是数组。

// 声明一个类数组对象 
var a = {
    0: 'hello',
    1: 'seg',
    2: 'ment',
    3: 'fault',
    length: 4
}

// forEach 
Array.prototype.forEach.call(a, elem => console.log(elem)); 
// => 遍历打印

// reduce 
var helloSF = Array.prototype.reduce.call(a, (acc, cur) => acc + cur + ' ', ''); 
console.log(helloSF); 
// => 
// "hello seg ment fault "


还可以做的更像数组

var a = {
    0: 'hello',
    1: 'seg',
    2: 'ment',
    3: 'fault',
    length: 4
}

a.__proto__ = Array.prototype; 
a.forEach(e => console.log(e)); 
Array.prototype.reduce.call(a, (acc, cur) => acc + cur + ' ', ''); 

Object Really Like Array

实现偏函数 Partial Function

跟数学上的偏函数类似,比如:

函数 f(x, y) = x + y
如果令 y = k 那么可以得到偏函数 f(x, k) = x + k
( 或者这样可能更好理解: f(x, 4) = x + 4 )

一般都是用 bind 来实现偏函数的。 不过 apply 和 call 和 bind 应该集中的讲讲。

function logger(type){
    return console.log.bind(console, type); 
}

用 apply 实现上述 logger 就是:

function logger2(type){
    return function(){
        var argu = Array.prototype.slice.call(arguments);  
        argu.unshift(type); 
        console.log.apply(console, argu); 
    }
}

高阶函数和柯里化

高阶函数一般指的是返回值是函数或者其参数是函数的函数。

setTimeout 是个很好的例子 它接受一个参数(一般是函数) 然后在一定时延后执行它。
不过传进去之后一般 this 就指向了 全局对象 window 如果想要钦点 this 就得用 call apply 和 bind

上面的 logger2 就做到了这点 返回了一个函数出去


关于柯里化 先看函数 add

function add(x, y){
    return a + b; 
}

add(1, 2); 
// => 
// 3 

如果参数能一个一个的传 传到第二个的时候就得出结果:

var add1 = add(1); 
add1(2); 
// => 3 

add(3)(4); 
// => 7

第一次执行返回了一个函数,如果把 add 看成是数学意义上的函数 那就是 f(x, y) = x + y 我们执行了一次 add(1) 得到 add1 其实就是令 x = 1 了,于是得到偏函数

f(1, y) = 1 + y

第二次再执行 y 会得到实际值 算式就可以算出结果出来。

这其实是一步步消元的过程。


有什么用的?

我在函数式编程方面也才初学,还没领会到精髓,唯一对柯里化体会的用处是 惰性求值
刚刚的运算在参数给齐之前不会运行 等到参数够了就会算出结果。


大半夜不睡觉刷sf 只能想到这些了。。。。

过去多啦不再A梦

手动设置this作用域。

迷茫

百度一下你就知道。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板