资讯专栏INFORMATION COLUMN

详解this、call和apply

yiliang / 1768人阅读

摘要:的指向除去不常用的和,的指向大致可分为以下四种作为对象的方法调用作为普通函数调用构造器调用或调用作为对象的方法调用当函数作为对象的方法被调用时,指向该对象。

this

和其他语言不同,JavaScript的this总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。

this的指向

除去不常用的witheval,this的指向大致可分为以下四种:

作为对象的方法调用

作为普通函数调用

构造器调用

Function.prototype.callFunction.prototype.apply调用

作为对象的方法调用

当函数作为对象的方法被调用时,this指向该对象。

var obj={
  a:1,
  getA:function(){
    alert(this===obj);//true
    alert(this.a);//1
  }
};

obj.getA();
作为普通函数调用

当函数不作为对象的属性被调用时,也就是普通函数方式,此时this总是指向全局对象。在浏览器中,这个全局对象是window

window.name="globalName";

var getName1=function(){
    return this.name;
};

var myObject={
    name:"sven",
    getName:function(){
        return this.name;
    }
};

var getName=myObject.getName;

alert(getName1());//globalName
alert(getName());//globalName
构造器调用

当用new运算符调用函数时,该函数总会返回一个对象,通常情况下,构造器里的this就指向返回的这个对象。

var MyClass=function(){
    this.name="sven";
};

var obj=new MyClass();
alert(obj.name);//sven

但是如果构造器显式地返回了一个object类型的对象,那么此次运算结果最终会返回这个对象,而不是我们之前期待的this:

var MyClass=function(){
    this.name="sven";
    return{
        name:"anne";
    }
};

var obj=new MyClass();
alert(obj.name);//anne

如果构造器不显式地返回任何数据,或者是返回一个非对象类型的数据,就不会造成上述问题:

var MyClass=function(){
    this.name="sven";
    return "anne";
};

var obj=new MyClass();
alert(obj.name);//sven
call和apply调用

call和apply可以动态的地改变传入函数的this:

var obj1={
    name:"sven",
    getName:function(){
        return this.name;
    }
};

var obj2={
    name:"anne"
};

console.log(obj1.getName());
console.log(obj1.getName.call(obj2));
call和apply

callapply作用一模一样,区别在于传入参数的形式不同。apply接受两个参数,第一个参数指定了函数体内this对象的指向,第二个参数第二个参数为一个带下标的集合,这个集合可以为数组,也可以为类数组。

JavaScript的参数在内部就是用一个数组来表示的,从这个意义上来说,applycall的使用率更高。call是包装在apply上的一颗语法糖,如果我们明确知道函数接受多少个参数,而且想一目了然地表达形参和实参的对应关系,那么也可以用call来传送参数。

当使用call或者apply时,如果我们传入的第一个参数是null,函数体内的this会指向默认的宿主对象,在浏览器中就是window,但如果是在严格模式下,函数体内的this还是为null

有时候我们使用call或者apply的目的并不在于指定this的指向,而是另有用途,比如借用其他对象的方法,那么我们就可以传入null来代替某个具体的对象。

call和apply的用途 改变this的指向 Function.prototype.bind
        Function.prototype.bind=function() {
        var self=this,
            context=[].shift.call(arguments),//需要绑定的this上下文
            args=[].slice.call(arguments);//剩余的参数转成数组
        return function(){
            return self.apply(context,[].concat.call(args,[].slice.call(arguments)));//执行新的函数体的时候,会把之前传入的context当作新函数体内的this,并且组合两次分别传入的参数,作为新函数的参数
        }
    };

    var obj={
        name:"sven"
    };

    var func=function(a,b,c,d){
        alert(this.name);
        alert([a,b,c,d]);
    }.bind(obj,1,2);

    func(3,4);
使用其他对象的方法

第一种场景是借用构造函数,可以实现一些类似继承的效果:

var A=function(name){
    this.name=name;
};

var B=function(){
    A.apply(this,arguments);
};

B.prototype.getName=function(){
    return this.name;
};

var b=new B("sven");
console.log(b.getName());

第二种场景:函数的参数列表arguments是一个类数组对象,虽然它也有下标,但她并非真正的数组,所以不能进行排序操作或者往集合里添加一个新的元素。这种情况下我们常常会借用Array.prototype对象上的方法。比如想往arguments里插入一个元素,通常会借用Array.prototype.push

(function(){Array.prototype.push.call(arguments,3)})(1,2);

在操作arguments时,我们经常非常频繁地找Array.prototype借用方法。

转化为数组:Array.prototype.slice

截去头元素:Array.prototype.shift

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86282.html

相关文章

  • JavaScript 中 applycall详解

    摘要:参数和是放在数组中传入函数,分别对应参数的列表元素。而原函数中的并没有被改变,依旧指向全局对象。保存原函数保存需要绑定的上下文剩余的参数转为数组返回一个新函数下一篇介绍闭包中闭包的详解。 apply 和 call 的区别 ECMAScript 规范给所有函数都定义了 call 与 apply 两个方法,它们的应用非常广泛,它们的作用也是一模一样,只是传参的形式有区别而已。 apply(...

    Meils 评论0 收藏0
  • 前端学习笔记之js中apply()call()方法详解

    摘要:第二行将函数的指向一个字符串第三行将函数的指向一个数字以此类推。再举一个例子实现对象继承继承了的属性和方法陈安东男姓名年龄性别输出姓名陈安东年龄性别男这样用就实现了继承用也类似 这里排版不是太好,详情看我的简书 经过网上的大量搜索,渐渐明白了apply()和call方法的使用,为此写一篇文章记录一下。 定义 apply()方法: Function.apply(obj,args)obj:...

    moven_j 评论0 收藏0
  • js 中的 call / apply 方法详解引用类型的继承

    摘要:也就是说当使用后,当前执行上下文中的对象已被替换为,后续执行将以所持有的状态属性继续执行。借用的方法替换的实例去调用相应的方法。实现引用类型的继承其实没有类这一概念,我们平时使用的等严格来说被称作引用类型。 call 方法:object.method.call(targetObj[, argv1, argv2, .....]) apply 方法:object.method.apply(...

    cod7ce 评论0 收藏0
  • call() , apply() 与 bind() 实例详解

    摘要:当没有使用而直接调用时指向对象函数和函数非常的相似,第一个参数都用来设置目标函数运行时的指向。输出的结果为结果证明两个地方传入的参数都会被传给目标函数,函数拷贝调用时传入的参数会追加在函数调用时传入的参数后面。 call() , apply() 与 bind() 详解 我们知道可以用call(), apply() 和 bind()这三个函数都是用来完成函数调用,并且设置this指向。 ...

    wayneli 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<