博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js函数调用模式和常用的几个方法
阅读量:7072 次
发布时间:2019-06-28

本文共 4339 字,大约阅读时间需要 14 分钟。

一、函数调用的4种模式

(1) 方法调用模式

当一个函数被保存为对象的一个属性时,我们称它为一个方法。当一个方法被调用时,this 被绑定到该对象。如果调用表达式包含一个提取属性的动作(即包含一个.点表达式或[subscript]下标表达式),那么它就是被当做一个方法来调用。

var myObj = {    value: 0,    increment: function (inc) {        this.value += typeof inc === 'number' ? inc : 1;    }};myObj.increment();console.log(myObj.value); // 1myObj.increment(2);console.log(myObj.value); // 3

(2) 函数调用模式

var add = function (a,b) {    return a + b;};var sum = add(3,4); // sum的值为7

以此模式调用函数时,this 被绑定到全局对象

延伸:调用内部函数时,如何把 this 绑定到外部函数的 this 变量上

// 承接上面代码// 给 myObj 增加一个 double 方法myObj.double = function() {    var that = this; // 解决方法    var helper = function () {        console.log(this); // this指向全局对象,如果写成this.value = add(this.value, this.value); 就获取不到正确的结果了        that.value = add(that.value, that.value);    };    helper(); // 以函数的形式调用 helper};myObj.double(); // 以方法的形式调用 doubleconsole.log(myObj.value); // 6

(3) 构造器调用模式

var Quo = function (string) {    this.status = string;}var myQuo = new Quo("confused"); // 构造一个 Quo 实例console.log(myQuo.status); // "confused"

一个函数,如果创建的目的就是希望结合new前缀来调用,那它就被称为构造(器)函数,函数内部的this 指向新创建的实例

(4) apply、call调用模式

js 是一门函数式的面向对象编程语言,函数也是一个对象,所以函数可以拥有自己的方法,apply、call就是其中的两种方法。

此种调用模式允许我们可以显式地设置 this 的指向,具体使用见下文。

二、函数常用的三个方法

1. fun.apply(thisArg[, argsArray])

在指定 this 值和参数(参数以数组类数组对象的形式存在)的情况下调用某个函数。

thisArg:在 fun 函数运行时指定的 this 值,如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动指向全局对象(浏览器中就是window对象)
argsArray:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。也可以使用 arguments 对象作为 argsArray 参数,用arguments把所有的参数传递给被调用对象。

/* 求一个数组中的最大最小值 */var numbers = [5, 6, 2, 3, 7];/* simple loop based algorithm */max = -Infinity, min = +Infinity;for (var i = 0; i < numbers.length; i++) {  if (numbers[i] > max)    max = numbers[i];  if (numbers[i] < min)     min = numbers[i];}/* vs. using Math.min/Math.max apply */var max = Math.max.apply(null, numbers); /* This about equal to Math.max(numbers[0], ...) or Math.max(5, 6, ..) */var min = Math.min.apply(null, numbers);

从上面的例子可以看到:本来需要写成遍历数组变量的任务,apply使用内建的函数就完成了。据此,可以简化某些对数组的操作

var arr1 = [1,2,3];var arr2 = [4,5,6];/* 如果我们要把 arr2 展开,然后一个一个追加到 arr1 中去,最后让 arr1=[1,2,3,4,5,6] * arr1.push(arr2)是不行的,因为这样做会得到[1,2,3,[4,5,6]]  * 可以循环arr2,然后一个一个的push,但是这样比较麻烦,使用apply,就so easy了 */Array.prototype.push.apply(arr1,arr2); console.log(arr1); // [1,2,3,4,5,6]/* 也可以用arr1.concat(arr2),但是concat方法返回的是一个新数组,并不改变arr1本身 */

2. fun.call(thisArg[, arg1[, arg2[, ...]]])

该方法的作用和 apply() 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表,而apply()方法接受的是一个包含多个参数的数组。

Math.max.apply(null, [1,2,3,4]);Math.max.call(null, 1, 2, 3, 4);/* eg. 使用call方法调用父构造函数 */function Animal(name){          this.name = name;          this.showName = function(){              console.log(this.name);          }      }          function Cat(name){        Animal.call(this, name); // 此行代码中的this指向Cat的实例   }          var cat = new Cat("Black Cat");     cat.showName(); // "Black Cat"

3. fun.bind(thisArg[, arg1[, arg2[, ...]]])

当在函数fun上调用bind( )方法并传入一个对象thisArg作为参数,这个方法将返回一个新函数。调用新的函数将会把原始的函数fun当做thisArg的方法来调用。

thisArg:当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。当使用new 操作符调用绑定函数时,该参数无效
arg1, arg2, ...:当绑定函数被调用时,这些参数加上绑定函数本身的参数会按照顺序作为原函数运行时的参数

// eg.1var sum = function (x,y) { return x + y; };var succ = sum.bind(null, 1);succ(2); // => 3: x绑定到1,并传入2作为实参y// eg.2function f(y,z) { return this.x + y + z; };var g = f.bind({x:1}, 2); // 绑定this和yg(3); // =>6: this.x绑定到1,y绑定到2,z绑定到3// eg.3 创建绑定函数this.x = 9; var module = {  x: 81,  getX: function() { return this.x; }};module.getX(); // 81var retrieveX = module.getX;retrieveX(); // 9, because in this case, "this" refers to the global object// Create a new function with 'this' bound to modulevar boundGetX = retrieveX.bind(module);boundGetX(); // 81

bind 函数在ES5版本中才被加入,ES3版本的bind( )方法实现如下(js权威指南p191):

if (!Function.prototype.bind) {    Function.prototype.bind = function(o[, args]) {        var self = this, boundArgs = arguments;                // bind()方法的返回值是一个函数        return function() {            // 创建一个实参列表,将传入bind()的第二个及后续的实参都传入这个函数            var args = [], i;            for(i = 1; i < boundArgs.length; i++) args.push(boundArgs[i]);            for(i = 0; i < arguments.length; i++) args.push(arguments[i]);            // 现在将self作为o的方法来调用,传入这些实参            return self.apply(o, args);        }    }}/* 关键点有二:一是改变this的指向,二是改变传入参数的个数  * * 上述代码并未实现ES5中bind方法的全部特性,但思路比较清晰明了,且满足大部分需求了 */

转载地址:http://suell.baihongyu.com/

你可能感兴趣的文章
常用算法Java实现之直接插入排序
查看>>
转载 radio值获取
查看>>
学习SpringMVC——你们要的REST风格的CRUD来了
查看>>
NLPIR数据语义挖掘技术为企业提供精准管理
查看>>
通过本地yum源安装软件报错[Errno 14] PYCURL ERROR 56 - "Failure when receiving data from the peer"...
查看>>
android常用调试工具fiddle、wireshark和android studio的配置
查看>>
Java实现几种常见排序方法
查看>>
NOIP2017 复盘
查看>>
jxa快速入门,Javascript已加入AppleScript全家桶
查看>>
洛谷P3622 动物园
查看>>
Angular Encapsulation - css选择器选不到非angular组件(插件)
查看>>
iOS开发之UIScrollView
查看>>
mysql 使用 insert ignore into和unique实现不插入重复数据功能
查看>>
c++操作符重载_12
查看>>
eclipse 安装反编译工具
查看>>
我的Java开发学习之旅------>Java多线程下载文件 实例
查看>>
WireShark简单使用以及TCP三次握手
查看>>
什么是@guid
查看>>
nodeType的12种类型
查看>>
步步为营 .NET 代码重构学习笔记 十三
查看>>