js中的call,apply,bind区别

在JavaScript中,callapplybindFunction对象自带的三个方法,这三个方法的主要作用是改变函数中的this指向。

callapplybind方法的共同点和区别:
apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文(函数的每次调用都会拥有一个特殊值——本次调用的上下文(context)——这就是this关键字的值。);
apply 、 call 、bind 三者都可以利用后续参数传参;
bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。

一、call

call()
语法:

call([thisObj[,arg1[, arg2[, [,.argN]]]]])

定义:调用一个对象的一个方法,以另一个对象替换当前对象。

说明: call 方法可以用来代替另一个对象调用一个方法。
call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

thisObj的取值有以下4种情况:
(1) 不传,或者传null,undefined, 函数中的this指向window对象
(2) 传递另一个函数的函数名,函数中的this指向这个函数的引用
(3) 传递字符串、数值或布尔类型等基础类型,函数中的this指向其对应的包装对象,如 String、Number、Boolean
(4) 传递一个对象,函数中的this指向这个对象

function a(){
  console.log(this);   //输出函数a中的this对象
}       

function b(){}       

var c={name:"call"};    //定义对象c  

a.call();   //window
a.call(null);   //window
a.call(undefined);   //window
a.call(1);   //Number
a.call(‘‘);   //String
a.call(true);   //Boolean
a.call(b);   //function b(){}
a.call(c);   //Object

如果你不理解上面的,没关系,我们再来看一个例子:

function class1(){
  this.name=function(){
    console.log("我是class1内的方法");
  }
}
function class2(){
  class1.call(this);  //此行代码执行后,当前的this指向了class1(也可以说class2继承了class1)
}   

var f=new class2();
f.name();   //调用的是class1内的方法,将class1的name方法交给class2使用

常用例子:
(1)

function eat(x,y){
  console.log(x+y);
}
function drink(x,y){
  console.log(x-y);
}
eat.call(drink,3,2);

输出:5

这个例子中的意思就是用 eat 来替换 drink,eat.call(drink,3,2) == eat(3,2) ,所以运行结果为:console.log(5);
注意:js 中的函数其实是对象,函数名是对 Function 对象的引用。

(2)

function Animal(){
  this.name="animal";
  this.showName=function(){
    console.log(this.name);
  }
}
function Dog(){
  this.name="dog";
}
var animal=new Animal();
var dog=new Dog();       

animal.showName.call(dog);

输出:dog

在上面的代码中,我们可以看到Dog里并没有showName方法,那为什么(this.name)的值是dog呢?

关键就在于最后一段代码(animal.showName.call(dog)),意思是把animal的方法放到dog上执行,也可以说,把animal 的showName()方法放到 dog上来执行,所以this.name 应该是 dog。

(3)继承

function Animal(name){
  this.name=name;
  this.showName=function(){
    console.log(this.name);
  }
}
function Dog(name){
  Animal.call(this,name);
}
var dog=new Dog("Crazy dog");
dog.showName();

输出:Crazy dog

Animal.call(this) 的意思就是使用 Animal对象代替this对象,那么Dog就能直接调用Animal的所有属性和方法。

二、apply()

语法:apply([thisObj[,argArray]])

定义:应用某一对象的一个方法,用另一个对象替换当前对象。

说明:
如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。
如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。

call 和 apply的区别
对于 apply、call 二者而言,作用完全一样,只是接受参数的方式不太一样。

function class1(args1,args2){
  this.name=function(){
   console.log(args,args);
  }
}
function class2(){
  var args1="1";
  var args2="2";
  class1.call(this,args1,args2);
  /*或*/
  class1.apply(this,[args1,args2]);
}

var c=new class2();
c.name();

输出:1 2

call 需要把参数按顺序传递进去,而 apply 则是把参数放在数组里。

既然两者功能一样,那该用哪个呢?

在JavaScript 中,某个函数的参数数量是不固定的,因此要说适用条件的话,当你的参数是明确知道数量时用 call ;而不确定的时候用 apply,然后把参数 push 进数组传递进去。当参数数量不确定时,函数内部也可以通过 arguments 这个数组来遍历所有的参数。

三、bind
bind是在EcmaScript5中扩展的方法(IE6,7,8不支持)
bind() 方法与 apply 和 call 很相似,也是可以改变函数体内 this 的指向。

  MDN的解释是:bind()方法会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入 bind()方法的第一个参数作为 this,传入 bind() 方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。

注意:bind方法的返回值是函数

var bar=function(){
  console.log(this.x);
}
var foo={
     x:3
}
bar();
bar.bind(foo)();
 /*或*/
var func=bar.bind(foo);
func();

输出:
undefined
3-------------------------------------------------------------下面就【借用一道面试题】,来更深入的去理解下 apply 和 call 。
function log(msg) {
  console.log(msg);
}
log(1);    //1
log(1,2);    //1
上面方法可以解决最基本的需求,但是当传入参数的个数是不确定的时候,上面的方法就失效了,这个时候就可以考虑使用 apply 或者 call,注意这里传入多少个参数是不确定的,所以使用apply是最好的,方法如下:
function log(){
  console.log.apply(console, arguments);
};
log(1);    //1
log(1,2);    //1 2

接下来的要求是给每一个 log 消息添加一个"(app)"的前辍,比如:

log("hello world");    //(app)hello world

该怎么做比较优雅呢?这个时候需要想到arguments参数是个伪数组,通过 Array.prototype.slice.call 转化为标准数组,再使用数组方法unshift,像这样:

function log(){
  var args = Array.prototype.slice.call(arguments);
  args.unshift(‘(app)‘);

  console.log.apply(console, args);
};

有个有趣的问题,如果连续 bind() 两次,亦或者是连续 bind() 三次那么输出的值是什么呢?像这样:

var bar = function(){
    console.log(this.x);
}
var foo = {
    x:3
}
var sed = {
    x:4
}
var func = bar.bind(foo).bind(sed);
func(); //?

var fiv = {
    x:5
}
var func = bar.bind(foo).bind(sed).bind(fiv);
func(); //?

答案是,两次都仍将输出 3 ,而非期待中的 4 和 5 。原因是,在Javascript中,多次 bind() 是无效的。更深层次的原因, bind() 的实现,相当于使用函数在内部包了一个 call / apply ,第二次 bind() 相当于再包住第一次 bind() ,故第二次以后的 bind 是无法生效的。

在常见的单体模式中,通常我们会使用 _this , that , self 等保存 this ,这样我们可以在改变了上下文之后继续引用到它。 像这样:

var foo = {
    bar : 1,
    eventBind: function(){
        var _this = this;
        $(‘.someClass‘).on(‘click‘,function(event) {
            /* Act on the event */
            console.log(_this.bar);     //1
        });
    }
}

由于 Javascript 特有的机制,上下文环境在 eventBind:function(){ } 过渡到 $(‘.someClass‘).on(‘click‘,function(event) { }) 发生了改变,上述使用变量保存 this 这些方式都是有用的,也没有什么问题。当然使用 bind() 可以更加优雅的解决这个问题:

var foo = {
    bar : 1,
    eventBind: function(){
        $(‘.someClass‘).on(‘click‘,function(event) {
            /* Act on the event */
            console.log(this.bar);      //1
        }.bind(this));
    }
}

转自:https://www.cnblogs.com/libin-1/p/6069031.html

原文地址:https://www.cnblogs.com/justdoyou/p/10201843.html

时间: 2025-01-03 20:32:43

js中的call,apply,bind区别的相关文章

js中的call apply bind简单总结

首先来看一个问题: 那如果此时就想要获取button按钮这个对象怎么解决? 结果: 还可以这样解决? 所以简单来说: call apply bind 的作用就是 改变函数内部this的指向.但是各自有点小区别. 再看: 如果不需要改变this的指向,就传入一个null就行. 应用: 原文地址:http://blog.51cto.com/11871779/2133119

JS中的call(),apply(),bind()方法

call,apply和bind到底有何用? 改变函数的this对象的指向 相似之处 1.都是用来改变函数的this对象指向 2.第一个参数都是this要指向的对象 3.都可以利用后续参数传参 先看下面例子: 例1: var name = "小王", age = 17; var obj = { name:"小张", objAge:this.age, myFun:function(){ console.log(this.name + "年龄" + t

JS中的call/apply/bind

<script> var obj = { a:1 } var a = 2; function test(a) { alert(a); alert(this.a); } </script> 1.test(3); 结果:"3"."2"; 解释:实参3传递给形参a,函数内部的形参a覆盖全局变量a,所以第一个为3,函数中this为window对象,所以this.a为2 2.test.call(thisObject,param1,param2...);

js中call、apply和bind的区别

前言 关于js中call.apply和bind这三者的区别,这应该是一个老生常谈的问题,也是前端面试时经常会遇到的一道题目,因此也抽空把它理一遍. 作用 call.apply和bind都是一个javascript中的方法,他们的共同作用就是改变函数执行时的上下文,即改变函数执行时this的指向.我们来看下面的例子: 1 function Animal(name) { 2 this.name = name; 3 } 4 Animal.prototype.getName = function() {

js中call,apply,bind的实现原理()

/* author:yangJian */ // js中call,apply,bind的实现原理() // 三者的区别,都是改变this指针,call和apply主要是参数区别,bind返回的是一个函数体,而call和apply是立即执行 // call的实现 function fn1 (str1,str2,str3){ console.log(this,str1,str2,str3); } function fn2(){ } Function.prototype.call = function

Javascript中call和apply的区别与详解

在js中call和apply它们的作用都是将函数绑定到另外一个对象上去运行,两者仅在定义参数方式有所区别,下面我来给大家介绍一下call和apply用法: 在web前端开发过程中,我们经常需要改变this指向,通常我们想到的就是用call方法: 说明:a.call(b,arg1,arg2..)就是a对象的方法应用到b对象上 a.apply(b,[arg1,arg2,....])也是a对象的方法应用到b对象上,只不过是第二个参数不一样而已: 例如: function add(a,b){alert(

js中 call 和 apply

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

JS中isPrototypeOf 和hasOwnProperty 的区别 ------- js使用in和hasOwnProperty获取对象属性的区别

JS中isPrototypeOf 和hasOwnProperty 的区别 1.isPrototypeOf isPrototypeOf是用来判断指定对象object1是否存在于另一个对象object2的原型链中,是则返回true,否则返回false. 格式如下: object1.isPrototypeOf(object2); object1是一个对象的实例: object2是另一个将要检查其原型链的对象. 原型链可以用来在同一个对象类型的不同实例之间共享功能. 如果 object2 的原型链中包含

Angular.js 中 copy 赋值与 = 赋值 区别

转自st.gg Angular.js 中 copy 赋值与 = 赋值 区别 为什么用 $scope.user = $scope.master; $scope.master 会跟着 $scope.user 改变?angular.copy 和 = 号赋值有什么区别呢?新手还没有搞懂,请教各位了. <!DOCTYPE html> <html> <script src= "http://apps.bdimg.com/libs/angular.js/1.3.9/angular