JavaScript 中 apply 、call 的详解

apply 和 call 的区别

ECMAScript 规范给所有函数都定义了 call 与 apply 两个方法,它们的应用非常广泛,它们的作用也是一模一样,只是传参的形式有区别而已。

apply( )

apply 方法传入两个参数:一个是作为函数上下文的对象,另外一个是作为函数参数所组成的数组。

var obj = {
 name : 'linxin'
}
function func(firstName, lastName){
 console.log(firstName + ' ' + this.name + ' ' + lastName);
}
func.apply(obj, ['A', 'B']); // A linxin B

可以看到,obj 是作为函数上下文的对象,函数 func 中 this 指向了 obj 这个对象。参数 A 和 B 是放在数组中传入 func 函数,分别对应 func 参数的列表元素。

call( )

call 方法第一个参数也是作为函数上下文的对象,但是后面传入的是一个参数列表,而不是单个数组。

var obj = {
 name: 'linxin'
}
function func(firstName, lastName) {
 console.log(firstName + ' ' + this.name + ' ' + lastName);
}
func.call(obj, 'C', 'D');  // C linxin D

对比 apply 我们可以看到区别,C 和 D 是作为单独的参数传给 func 函数,而不是放到数组中。

对于什么时候该用什么方法,其实不用纠结。如果你的参数本来就存在一个数组中,那自然就用 apply,如果参数比较散乱相互之间没什么关联,就用 call。

apply 和 call 的用法

1.改变 this 指向

var obj = {
 name: 'linxin'
}
function func() {
 console.log(this.name);
}
func.call(obj);  // linxin

我们知道,call 方法的第一个参数是作为函数上下文的对象,这里把 obj 作为参数传给了 func,此时函数里的 this 便指向了 obj 对象。此处 func 函数里其实相当于

function func() {
 console.log(obj.name);
}

2.借用别的对象的方法

先看例子

var Person1 = function () {
 this.name = 'linxin';
}
var Person2 = function () {
 this.getname = function () {
  console.log(this.name);
 }
 Person1.call(this);
}
var person = new Person2();
person.getname();  // linxin

从上面我们看到,Person2 实例化出来的对象 person 通过 getname 方法拿到了 Person1 中的 name。因为在 Person2 中,Person1.call(this) 的作用就是使用 Person1 对象代替 this 对象,那么 Person2 就有了 Person1 中的所有属性和方法了,相当于 Person2 继承了 Person1 的属性和方法。

3.调用函数

apply、call 方法都会使函数立即执行,因此它们也可以用来调用函数。

function func() {
 console.log('linxin');
}
func.call();   // linxin

call 和 bind 的区别

在 EcmaScript5 中扩展了叫 bind 的方法,在低版本的 IE 中不兼容。它和 call 很相似,接受的参数有两部分,第一个参数是是作为函数上下文的对象,第二部分参数是个列表,可以接受多个参数。

它们之间的区别有以下两点。

1.bind 发返回值是函数

var obj = {
 name: 'linxin'
}
function func() {
 console.log(this.name);
}
var func1 = func.bind(obj);
func1();      // linxin

bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数。而原函数 func 中的 this 并没有被改变,依旧指向全局对象 window。

2.参数的使用

function func(a, b, c) {
 console.log(a, b, c);
}
var func1 = func.bind(null,'linxin');
func('A', 'B', 'C');   // A B C
func1('A', 'B', 'C');   // linxin A B
func1('B', 'C');    // linxin B C
func.call(null, 'linxin');  // linxin undefined undefined

call 是把第二个及以后的参数作为 func 方法的实参传进去,而 func1 方法的实参实则是在 bind 中参数的基础上再往后排。

在低版本浏览器没有 bind 方法,我们也可以自己实现一个。

if (!Function.prototype.bind) {
 Function.prototype.bind = function () {
  var self = this,      // 保存原函数
   context = [].shift.call(arguments), // 保存需要绑定的this上下文
   args = [].slice.call(arguments); // 剩余的参数转为数组
  return function () {     // 返回一个新函数
   self.apply(context,[].concat.call(args, [].slice.call(arguments)));
  }
 }
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持我们!

(0)

相关推荐

  • JS中改变this指向的方法(call和apply、bind)

    this是javascript的一个关键字,随着函数使用场合不同,this的值会发生变化.但是总有一个原则,那就是this指的是调用函数的那个对象. this一般指向的是当前被调用者,但也可以通过其它方式来改变它的指向,下面将介绍三种方式: 1.call用作继承时: function Parent(age){ this.name=['mike','jack','smith']; this.age=age; } function Child(age){ Parent.call(this,age);

  • Javascript中call,apply,bind方法的详解与总结

    以下内容会分为如下小节: 1.call/apply/bind方法的来源 2.Function.prototype.call() 3.Function.prototype.apply() 3.1:找出数组中的最大数 3.2:将数组的空元素变为undefined 3.3:转换类似数组的对象 4.Function.prototype.bind() 5.绑定回调函数的对象 6.call,apply,bind方法的联系和区别 1.call/apply/bind方法的来源 首先,在使用call,apply,

  • 实例讲解JavaScript中call、apply、bind方法的异同

    以实例切入,讲解JavaScript中call,apply,bind方法,供大家参考,具体内容如下 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script type="text/javascript"> function MAN(name, sex, age) { this.name =

  • js apply/call/caller/callee/bind使用方法与区别分析

    一.call 方法 调用一个对象的一个方法,以另一个对象替换当前对象(其实就是更改对象的内部指针,即改变对象的this指向的内容). Js代码 call([thisObj[,arg1[, arg2[, [,.argN]]]]]) 参数 thisObj 可选项.将被用作当前对象的对象. arg1, arg2, , argN 可选项.将被传递方法参数序列. 说明 call 方法可以用来代替另一个对象调用一个方法.call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对

  • js中call与apply的用法小结

    前天去面试,有个gg问了一些js知识,其中有一道call与apply用法的题目,尽管在365天前用过call方法,但当时还是没能答上来,今天深入总结一下 call和apply,它们的作用都是将函数绑定到另外一个对象上去运行 两者的格式和参数定义: call( thisArg [,arg1,arg2,- ] );       // 参数列表,arg1,arg2,...apply(thisArg [,argArray] );                 // 参数数组,argArray 上面两个

  • 浅谈JavaScript中的apply/call/bind和this的使用

    fun.apply(context,[argsArray]) 立即调用fun,同时将fun函数原来的this指向传入的新context对象,实现同一个方法在不同对象上重复使用. context:传入的对象,替代fun函数原来的this: argsArray:一个数组或者类数组对象,其中的数组参数会被展开作为单独的实参传给 fun 函数,需要注意参数的顺序. fun.call(context,[arg1],[arg2],[-]) 同apply,只是参数列表不同,call的参数需要分开一个一个传入.

  • js中继承的几种用法总结(apply,call,prototype)

    一,js中对象继承 js中有三种继承方式 1.js原型(prototype)实现继承 复制代码 代码如下: <SPAN style="BACKGROUND-COLOR: #ffffff"><SPAN style="FONT-SIZE: 18px"><html>  <body>  <script type="text/javascript">      function Person(na

  • 详解js中的apply与call的用法

    前言 call 和 apply 都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向. call 和 apply二者的作用完全一样,只是接受参数的方式不太一样. 方法定义 apply Function.apply(obj,args)方法能接收两个参数: obj:这个对象将代替Function类里this对象 args:这个是数组或类数组,apply方法把这个集合中的元素作为参数传递给被调用的函数. call call方法与apply方

  • JavaScript中的apply()方法和call()方法使用介绍

    1.每个函数都包含两个非继承而来的方法:apply()和call(). 2.他们的用途相同,都是在特定的作用域中调用函数. 3.接收参数方面不同,apply()接收两个参数,一个是函数运行的作用域(this),另一个是参数数组.call()方法第一个参数与apply()方法相同,但传递给函数的参数必须列举出来. 例1: 复制代码 代码如下: window.firstName = "diz"; window.lastName = "song"; var myObjec

  • javascript中Array()数组函数详解

    在程序语言中数组的重要性不言而喻,JavaScript中数组也是最常使用的对象之一,数组是值的有序集合,由于弱类型的原因,JavaScript中数组十分灵活.强大,不像是Java等强类型高级语言数组只能存放同一类型或其子类型元素,JavaScript在同一个数组中可以存放多种类型的元素,而且是长度也是可以动态调整的,可以随着数据增加或减少自动对数组长度做更改. Array()是一个用来构建数组的内建构造器函数.数组主要由如下三种创建方式: array = new Array() array =

  • JavaScript中eval()函数用法详解

    eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行. 如果参数是一个表达式,eval() 函数将执行表达式.如果参数是Javascript语句,eval()将执行 Javascript 语句. 语法 复制代码 代码如下: eval(string) 参数 描述 string 必需.要计算的字符串,其中含有要计算的 JavaScript 表达式或要执行的语句. eval()函数用法详解: 此函数可能使用的频率并不是太高,但是在某些情况下具有很大的作用,下面就介绍一下eva

  • JavaScript中 ES6 generator数据类型详解

    1. generator简介 generator 是ES6引入的新的数据类型, 看上去像一个函数,除了使用return返回, yield可以返回多次. generator 由function* 定义, (注意*号), 2. 示例 函数无法保存状态, 有时需要全局变量来保存数字: 2.1 'use strict'; function next_id(){ var id = 1; while(id<100){ yield id; id++; } return id; } // 测试: var x,

  • javascript 中的继承实例详解

    javascript 中的继承实例详解 阅读目录 原型链继承 借用构造函数 组合继承 寄生组合式继承 后记 继承有两种方式:接口继承和实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法. 由于函数没有签名,在ECMAScript中无法实现接口继承.ECMAScript只支持实现继承,而且实现继承主要依靠原型链来实现. 下面介绍几种js的继承: 原型链继承 原型链继承实现的本质是重写原型对象,代之以一个新类型的实例.代码如下: function SuperType() { this.pr

  • JavaScript中的函数式编程详解

    函数式编程 函数式编程是一种编程范式,是一种构建计算机程序结构和元素的风格,它把计算看作是对数学函数的评估,避免了状态的变化和数据的可变,与函数式编程相对的是命令式编程.我们有这样一个需求,给数组的每个数字加一: // 数组每个数字加一, 命令式编程 let arr = [1, 2, 3, 4]; let newArr = []; for(let i = 0; i < arr.length; i++){ newArr.push(arr[i] + 1); } console.log(newArr)

  • Javascript中window.name属性详解

    关于window下自带name的属性 不知道大家有没有发现这样一种情况 在控制台里直接输出未声明变量,正常情况应该是会报错的,而且声明未赋值的变量输出应该是undefined var a; //undefined b; //报错 但是偏偏就个别特例,就是name属性 其实window自身就带有name这个属性,在控制台输入window可以可以看到 打开 往下翻就可以找到 window.name直译过来是窗口名字,主要用于为超链接和表单设置目标(targets),什么意思呢,我们做个案例 建立两个

  • JavaScript中BOM和DOM详解

    目录 BOM(浏览器对象模型) 1. window 获取浏览器c窗口尺寸 2. screen 获取电脑屏幕大小 3. window 开启关闭窗口 4. 浏览器事件 5. location 6. history 7. navigator 获取浏览器相关信息 8. 弹窗 DOM (文档对象模型) DOM 分类 DOM对象 Document文档对象 element文档对象 DOM事件操作 鼠标事件 键盘事件 触屏事件 特殊事件 表单事件 浏览器兼容处理 兼容性写法,封装工具 BOM(浏览器对象模型)

  • JavaScript中深拷贝与浅拷贝详解

    目录 1 浅拷贝概念 2 深拷贝概念 3 浅拷贝的实现方式 3.1 Object.assign() 3.2 Array.prototype.concat() 3.3 Array.prototype.slice() 3.4 直接赋值 4 深拷贝的实现方式 4.1 JSON.parse(JSON.stringify()) 4.2 函数库lodash 总结 1 浅拷贝概念 深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的. 浅拷贝是创建一个新对象,该对象有着原始对象属性值的一份精确拷

  • JavaScript中的this使用详解

    其实this是一个老生常谈的问题了.关于this的文章非常多,其实我本以为自己早弄明白了它,不过昨天在做项目的过程中,还是出现了一丝疑惑,想到大概之前在JavaScript weekly里收藏待看的一篇详解this的文章(后有链接,也附上了稀土上的中文译文)和另一篇一位前辈推荐的文章,就把它们看了看,对this的认识确实提升了一些. JavaScript 中的'this'是动态的,它在函数运行时被确定而非在函数声明时被确定.所有的函数都可以调用'this',这无关于该函数是否属于某个对象.关于t

  • javascript中json基础知识详解

    大致介绍 JSON(JavaScript Object Notation  JavaScript对象表示法),JSON是一种数据格式,不是一种编程语言.虽然它的名字中有JavaScript但是它却不属于JavaScript,就像Java和JavaScript的关系一样.而且,并不是只有JavaScript才使用它,毕竟 JSON 只是一种数据格式.很多编程语言都有针对 JSON 的解析器和序列化器. JSON是由Douglas Crockford在2001年提出,为了取代XML 语法 JSON的

随机推荐