V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
eniac0001
V2EX  ›  JavaScript

JavaScript 中使用 Call 或 Apply 扩展的好处是什么?

  •  
  •   eniac0001 · 2016-01-23 10:39:36 +08:00 · 3497 次点击
    这是一个创建于 3013 天前的主题,其中的信息可能已经有所发展或是发生改变。

    例如对 String 添加 reverse 方法,一般是这样写:

    String.prototype.reverse = function() {
    return Array.prototype.reverse.apply(this.split("")).join();
    }

    可不可以这样写:

    String.prototype.reverse = function() {
    return this.split("").reverse().join();
    }

    上面的写法比下面的写法有什么好处呢?

    21 条回复    2016-01-24 19:11:24 +08:00
    runcelim
        1
    runcelim  
       2016-01-23 10:56:57 +08:00
    String 通过 apply 或 call 借用 Array 的 reverse 实现方法
    sagnitude
        2
    sagnitude  
       2016-01-23 11:47:01 +08:00   ❤️ 2
    为了写起来方便,自由度更大。比如 func.apply(null, arguments),改变 this ,使用 arguments ,还有 Array.prototype.slice.call(arguments),强行调用其他对象的方法,

    另外的区别就是 apply 比 call 慢, call 比直接调用慢, bind 方法比这些都慢
    另外, string 的 reverse 方法,用 for 循环比这两个都快
    另外, join 方法不带参数默认使用逗号作为分隔符
    Keita1314
        3
    Keita1314  
       2016-01-23 12:27:56 +08:00
    1 是指定 this
    2 是有些情况,比如类数组对象,根本就没有 reverse 这个方法可以调用,只能通过借用 Array 的方法来实现
    oott123
        4
    oott123  
       2016-01-23 13:21:33 +08:00
    感觉在 LZ 给的例子里,完全没必要用 Array.prototype.reverse.call
    倒是像这样的场景可能需要:
    str = "Hello world!"
    Array.prototype.slice.call(str, 1, 3).join('')
    > "el"
    shyling
        5
    shyling  
       2016-01-23 13:31:33 +08:00 via iPad
    1 。想改变 this 时
    2 。例如想遍历 NodeList 时用 Array.prototype.forEach.call
    3 。用 arguments 时配合 apply
    breeswish
        6
    breeswish  
       2016-01-23 14:16:03 +08:00
    楼主给的例子里上面写法没什么用..
    BOYPT
        7
    BOYPT  
       2016-01-23 14:24:50 +08:00
    最主要就是改变调用栈。不过如果用了框架比如 jquery.proxy, _.bind 之类的封装就可以不需要用 apply call 了,一般来说。原生党比较最爱。
    iyangyuan
        8
    iyangyuan  
       2016-01-23 14:49:40 +08:00 via iPhone
    复用
    eniac0001
        9
    eniac0001  
    OP
       2016-01-23 16:45:15 +08:00
    eniac0001
        10
    eniac0001  
    OP
       2016-01-23 16:47:04 +08:00
    @iyangyuan 谢谢!
    eniac0001
        11
    eniac0001  
    OP
       2016-01-23 16:48:21 +08:00
    @oott123 @breeswish Sorry ,我例子的问题,怪不得看了半天没看出明显的差异!
    eniac0001
        12
    eniac0001  
    OP
       2016-01-23 16:48:53 +08:00
    @BOYPT 谢谢!
    eniac0001
        13
    eniac0001  
    OP
       2016-01-23 16:50:49 +08:00
    @sagnitude 考虑的很仔细,多谢!
    ChefIsAwesome
        14
    ChefIsAwesome  
       2016-01-23 16:58:53 +08:00
    apply 能用数组的形式给函数传参,这个特性很有用的。
    有些人设计的函数是这样的
    `function (arg1, arg2, arg3, ...) { }`
    参数数量不限,但是必须一个一个写。如果你的参数是从其他地方以数组的形式过来的,那用 apply 就很方便了。
    chemzqm
        15
    chemzqm  
       2016-01-23 17:00:50 +08:00
    改变内部 this ,做工具库经常用的 ,有一个特别常用的,将 NodeList 转化为数组

    Array.prototype.silce.call(document.querySelector('.item'))

    用 new Array 创建性能更好,就是代码多点
    alsotang
        16
    alsotang  
       2016-01-23 20:31:50 +08:00
    所以楼上各位大大,楼主列举的那两种写法,到底上面那种好在哪里呢?
    breeswish
        17
    breeswish  
       2016-01-23 21:54:36 +08:00
    @oott123 其实这种场景也可以直接 #String.slice 的 :-)
    lxrmido
        18
    lxrmido  
       2016-01-23 22:58:10 +08:00
    @alsotang

    没好处
    eniac0001
        19
    eniac0001  
    OP
       2016-01-24 10:26:19 +08:00
    @alsotang 列举的两个例子不好,可以参考 @oott123 的例子研究一下。。。
    oott123
        20
    oott123  
       2016-01-24 10:33:06 +08:00
    @eniac0001 我的例子也不好, @breeswish 说得对,在新标准里 String 已经有 slice 方法了…不过你可以当他没有 hhhh
    eniac0001
        21
    eniac0001  
    OP
       2016-01-24 19:11:24 +08:00
    @All 列举的例子不好,主要是 String 调用 split 后正好是数组了,所以正好可以使用 reverse 方法;而在正常情况下,一个类型 A 是没有直接的转换的方法可以转换为类型 B 的,所以在 A 使用 B 的方法时,使用:
    B.prototype.method.apply(A, arguments);
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3277 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 13:00 · PVG 21:00 · LAX 06:00 · JFK 09:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.