谈谈JavaScript中的几种借用方法_基础知识

前言

通过call()、apply()和bind()方法,我们可轻易地借用其它对象的方法,而无须从这些对象中继承它。

在JavaScript中借用方法

在JavaScript中,有时可以重用其它对象的函数或方法,而不一定非得是对象本身或原型上定义的。通过 call()、apply() 和 bind() 方法,我们可轻易地借用其它对象的方法,而无须继承这些对象。这是专业 JavaScript 开发者常用的手段。

原型方法

在 JavaScript 中,除了不可更改的原始数据类型,如 string、number 和 boolean,几乎所有的数据都是对象。Array 是一种适用于遍历和转换有序数列的对象,其原型上有 slice、join、push 和 pop 等好用的方法。

一个常用的例子是,当对象和数组都是列表类型的数据结构时,对象可以从数组“借用”方法。最常借用的方法是 Array.prototype.slice

function myFunc() {

  // error, arguments is an array like object, not a real array
  arguments.sort();

  // "borrow" the Array method slice from its prototype, which takes an array like object (key:value)
  // and returns a real array
  var args = Array.prototype.slice.call(arguments);

  // args is now a real Array, so can use the sort() method from Array
  args.sort();

}

myFunc('bananas', 'cherries', 'apples');

借用方法之所以可行,是因为 call 和 apply 方法允许在不同上下文中调用函数,这也是重用已有功能而不必继承其它对象的好方法。实际上,数组在原型中定义了很多常用方法,比如 join 和 filter 也是:

// takes a string "abc" and produces "a|b|c
Array.prototype.join.call('abc', '|');

// takes a string and removes all non vowels
Array.prototype.filter.call('abcdefghijk', function(val) {
  return ['a', 'e', 'i', 'o', 'u'].indexOf(val) !== -1;
}).join('');

可以看出,不仅对象可以借用数组的方法,字符串也可以。但是因为泛型方法是在原型上定义的,每次想要借用方法时都必须使用 String.prototype Array.prototype。这样写很啰嗦,很快就会令人生厌。更有效的方法是使用字面量来达到同样的目的。

使用字面量借用方法

字面量是一种遵循JavaScript规则的语法结构,MDN 这样解释:

在JavaScript中,使用字面量可以代表值。它们是固定值,不是变量,就是在脚本中按字面给出的。
字面量可以简写原型方法:

[].slice.call(arguments);
[].join.call('abc', '|');
''.toUpperCase.call(['lowercase', 'words', 'in', 'a', 'sentence']).split(',');

这样看上去没有那么冗长了,但是必须直接在 [] 和 "" 上操作以借用方法,仍然有点丑。可以利用变量保存对字面量和方法的引用,这样写起来更简便些:

var slice = [].slice;
slice.call(arguments);
var join = [].join;
join.call('abc', '|');

var toUpperCase = ''.toUpperCase;
toUpperCase.call(['lowercase', 'words', 'in', 'a', 'sentence']).split(',');

有了借用方法的引用,我们就可以轻松地使用 call() 调用它了,这样也可以重用代码。秉着减少冗余的原则,我们来看看可否借用方法却不用每次调用都要写 call() 或者 apply():

var slice = Function.prototype.call.bind(Array.prototype.slice);
slice(arguments);

var join = Function.prototype.call.bind(Array.prototype.join);
join('abc', '|');

var toUpperCase = Function.prototype.call.bind(String.prototype.toUpperCase);
toUpperCase(['lowercase', 'words', 'in', 'a', 'sentence']).split(',');

如你所见,现在可以使用 Function.prototype.call.bind 来静态绑定从不同原型“借来的”方法了。但是 var slice = Function.prototype.call.bind(Array.prototype.slice) 这句话实际是如何起作用的呢?

理解 Function.prototype.call.bind

Function.prototype.call.bind 乍一看有些复杂,但是理解它是如何起作用的会非常有益。

Function.prototype.call 是一种引用,可以“call”函数并将设置其“this”值以在函数中使用。
注意“bind”返回一个存有其“this”值的新函数。因此 .bind(Array.prototype.slice) 返回的新函数的“this”总是 Array.prototype.slice 函数。

综上所述,新函数会调用“call”函数,并且其“this”为“slice”函数。调用 slice() 就会指向之前限定的方法。

自定义对象的方法

继承很棒,但是开发者通常在想要重用一些对象或模块间的通用功能时才会使用。没必要仅为代码重用使用继承,因为在多数情况下简单的借用方法会很复杂。

之前我们只讨论了借用原生方法,但是借用任何方法都是可以的。比如下面的代码可以计算积分游戏的玩家分数:

var scoreCalculator = {
  getSum: function(results) {
    var score = 0;
    for (var i = 0, len = results.length; i < len; i++) {
      score = score + results[i];
    }
    return score;
  },
  getScore: function() {
    return scoreCalculator.getSum(this.results) / this.handicap;
  }
};
var player1 = {
  results: [69, 50, 76],
  handicap: 8
};

var player2 = {
  results: [23, 4, 58],
  handicap: 5
};

var score = Function.prototype.call.bind(scoreCalculator.getScore);

// Score: 24.375
console.log('Score: ' + score(player1));

// Score: 17
console.log('Score: ' + score(player2));

虽然上面的例子很生硬,但是可以看出,就像原生方法一样,用户定义的方法也可以轻松借用。

总结

Call、bind 和 apply 可以改变函数的调用方式,并且经常在借用函数时使用。多数开发者熟悉借用原生方法,但是较少借用自定义的方法。

近几年 JavaScript 的函数式编程发展不错,怎样使用 Function.prototype.call.bind 借用方法才更加简便?估计这样的话题会越来越常见。

以上就是JavaScript中的借用方法总结的全部内容,希望对大家了解到JavaScript中的借用方法有所帮助吧。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索javascript
, 方法
, call方法
javascript常用方法
javascript基础知识、javascript基础知识点、javascript 基础教程、零基础学javascript、javascript知识点总结,以便于您获取更多的相关知识。

时间: 2024-12-04 00:25:48

谈谈JavaScript中的几种借用方法_基础知识的相关文章

JavaScript中OnLoad几种使用方法_基础知识

在前几个项目的开发中 遇到onload使用的几种情形 1. 可以在Body 里面执行 <body onload="alert(123)"></body>2. 先定义好 在页面加载完成后使用 复制代码 代码如下: <script type="text/javascript"> function test(){ var aa = "嘻嘻,你个大猪猪"; alert(aa); } window.onload = te

深入了解JavaScript中的Symbol的使用方法_基础知识

Symbol 是什么? Symbols 不是图标,也不是指在代码中可以使用小图片: 也不是指代其他一些东西的语法.那么,Symbol 到究竟是什么呢?七种数据类型 JavaScript 在 1997 年被标准化时,就有 6 种数据类型,直到 ES6 出现之前,程序中的变量一定是以下 6 种数据类型之一:     Undefined     Null     Boolean     Number     String     Object 每种数据类型都是一系列值的组合,前面 5 种数据类型值的数

简单谈谈javascript中this的隐式绑定_基础知识

我们先来看一个例子 function foo() { console.log( this.a ); } var obj = { a: 2, foo: foo }; obj.foo(); // 2 this指向了obj,因为foo执行时的call-site(可以理解为调用时所在作用域)在obj上面.注意是运行的时候,和在哪里声明的没有关系. call-site and call-stack call-site姑且理解为调用域,call-stack为调用栈.如下代码可以辅助我们理解 function

JavaScript中length属性的使用方法_基础知识

 此属性返回字符串中的字符数. 语法 string.length 下面是参数的详细信息:     A string 返回值: 返回字符串中的字符数. 例子: <html> <head> <title>JavaScript String length Property</title> </head> <body> <script type="text/javascript"> var str = new

在JavaScript中使用NaN值的方法_基础知识

 不带引号的字面常量NaN是一个特殊的值,表示不是非数字.由于NaN总是比较不等的情况,以任何数,包括NaN,它通常是用于指示应该返回一个有效的数的函数的错误条件. 注意:使用isNaN()全局函数来查看是否值是NaN值.语法 您可以使用以下语法访问属性: var val = Number.NaN; 示例 : 在这里,dayOfMonth分配NaN,如果是大于31,并显示一条消息,表明有效范围: <html> <head> <script type="text/ja

JavaScript中字符串拼接的基本方法_基础知识

非常简单,就用一个"+"将两个字符串"相加": var longString = "One piece " + "plus one more piece.";       要将多个字符串累积为一个字符串,还可以使用"+="操作符: var result = ""; result += "My name is Anders" result += " and m

简单介绍JavaScript中字符串创建的基本方法_基础知识

创建一个字符串有几种方法.最简单的是用引号将一组字符包含起来,可以将其赋值给一个字符串变量. var myStr = "Hello, String!";       可以用双引号或单引号将字符串包含,但要注意,作为界定字符串的一对引号必须是相同的,不能混用.       像var myString = "Fluffy is a pretty cat.'; 这样的声明就是非法的.       允许使用两种引号,使得某些操作变得简单,比如将一种嵌入另外一种: document.w

实例分析javascript中的call()和apply()方法_基础知识

1.方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象. 说明: call 方法可以用来代替另一个对象调用一个方法.call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象. 如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj. apply方法: 语法:apply([thisObj[,argArray]])

JavaScript中的6种运算符总结_基础知识

JavaScript 运算符主要包括: 算术运算符 赋值运算符 比较运算符 三元运算符 逻辑运算符 字符串连接运算符 算术运算符 运算符 说明 例子 运算结果 + 加 y = 2+1 y = 3 - 减 y = 2-1 y = 1 * 乘 y = 2*3 y = 6 / 除,返回结果为浮点类型 y = 6/3 y = 2 % 求余,返回结果为浮点类型 要求两个操作数均为整数 y = 6%4 y = 2 ++ 递加,分为前加和后加 对布尔值和 NULL 将无效 y = 2 ++y(前加) y++(