javascript - 为什么 String.methods 上的 .call 除了在 Firefox 中不起作用

标签 javascript string node.js google-chrome firefox

我想知道是否尝试将数组中的所有小写项目转换为大写。 我正在评估一些变体并检查了 .call() 变体是最快的变体 ( http://jsperf.com/uppercaseperformance )

的性能

使用以下代码,该代码在 Firefox (32.0.1) 中运行良好:

console.log(String.toUpperCase.call(null,['a', 'lower', 'case', 'string', 'array']))

仅在 Firefox 中输出:

A,LOWER,CASE,STRING,ARRAY <- Thats nice ;)

相同的代码在 Chrome、Safari、node.js 等中不起作用。 Chrome/Safari 输出:

TypeError: Cannot read property 'call' of undefined

node.js 输出:

TypeError: Cannot call method 'call' of undefined

.call 是否可能在错误的上下文中使用? MDN上的浏览器兼容性网站显示应支持 .call()

最佳答案

String generic methods不是 ECMAScript 标准的一部分,它们仅在 Firefox 中提供。

您可以为所有其他浏览器填充它(直接从 MDN 复制):

/*globals define*/
// Assumes all supplied String instance methods already present
// (one may use shims for these if not available)
(function () {
    'use strict';

    var i,
        // We could also build the array of methods with the following, but the
        //   getOwnPropertyNames() method is non-shimable:
        // Object.getOwnPropertyNames(String).filter(function (methodName)
        //  {return typeof String[methodName] === 'function'});
        methods = [
            'quote', 'substring', 'toLowerCase', 'toUpperCase', 'charAt',
            'charCodeAt', 'indexOf', 'lastIndexOf', 'startsWith', 'endsWith',
            'trim', 'trimLeft', 'trimRight', 'toLocaleLowerCase',
            'toLocaleUpperCase', 'localeCompare', 'match', 'search',
            'replace', 'split', 'substr', 'concat', 'slice'
        ],
        methodCount = methods.length,
        assignStringGeneric = function (methodName) {
            var method = String.prototype[methodName];
            String[methodName] = function (arg1) {
                return method.apply(arg1, Array.prototype.slice.call(arguments, 1));
            };
        };

    for (i = 0; i < methodCount; i++) {
        assignStringGeneric(methods[i]);
    }
}());
<小时/>

请注意,使用上面的垫片只是在此基础上添加一些抽象:

String.prototype.toUpperCase.apply(['a', 'lower', 'case', 'string', 'array']);
// "A,LOWER,CASE,STRING,ARRAY"

这里有趣的部分是数组被用作 String 方法的 this 值。

根据规范( § 15.5.4.18 -> § 15.5.4.16 步骤 2),this 绑定(bind)通过内部 ToString 强制转换为字符串。算法,对于对象(注意数组是对象)调用内部 ToPrimitive算法,该算法依次调用数组的 toString方法,该方法又调用数组的 join具有空参数列表的方法。

也就是说,调用 .toUpperCase() 将数组作为 this 绑定(bind)传递将首先将 this 隐式强制为字符串:

['a', 'b'].toString() === ['a', 'b'].join();
['a', 'b'].join() === 'a,b';

然后 toUpperCase 会将此字符串的字符映射为其等效的大写字符。因此:

String.prototype.toUpperCase.apply(['a', 'b']) === ['a', 'b'].join().toUpperCase();

关于javascript - 为什么 String.methods 上的 .call 除了在 Firefox 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25922918/

相关文章:

node.js - 在 adonis.js/node.js 中请求后保存 user_id 的中间件

Javascript 图像预加载无法正常工作

javascript - 如何在html中以编程方式清除缓存?

javascript - 为什么在 javascript "100"< "5"返回 true ?

c++ - 如何在不导入任何库的情况下删除 vector

node.js - 需要对属于一篇文章的多个评论做关系 MongoDB

javascript - 动态选择框在 IE7 中未正确居中

javascript - 如何在文本输入 HTML 中添加多个电子邮件地址

MySQL 搜索字符串首先以 string 开头,但也会返回包含 string 的任何结果

javascript - gulp-foreach 不循环遍历所有文件