搜索

首页  >  问答  >  正文

javascript - 关于apply()与call()的问题

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()的在项目中应用价值是什么呢?

滿天的星座滿天的星座2707 天前1170

全部回复(5)我来回复

  • 淡淡烟草味

    淡淡烟草味2017-07-05 11:03:57

    楼上写的真复杂:)

    听我讲讲,题主疑惑的地方
    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...

    回复
    0
  • typecho

    typecho2017-07-05 11:03:57

    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。

    回复
    0
  • 巴扎黑

    巴扎黑2017-07-05 11:03:57

    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 只能想到这些了。。。。

    回复
    0
  • 过去多啦不再A梦

    过去多啦不再A梦2017-07-05 11:03:57

    手动设置this作用域。

    回复
    0
  • 迷茫

    迷茫2017-07-05 11:03:57

    百度一下你就知道。

    回复
    0
  • 取消回复