资讯专栏INFORMATION COLUMN

浅谈javascript里面的this、call、apply、bind

Lemon_95 / 3508人阅读

摘要:如果该参数的值为或,则表示不需要传入任何参数,从开始可以使用类数组对象。当使用操作符调用绑定函数时,该参数无效。当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。

在了解call,apply之前需要先了解下javascrit中this指向

this的指向
在ES5里面,this永远指向最后调用它的那个对象
举个栗子:

var name = "outerName";
function test(){
    var name = "innerName";
    console.log(this.name);  //outerName
    console.log("inner:" + this);  //inner:Window
}
test();
console.log("outer:"+this);//outer:Window

我们最后调用test的地方test();,前面没有调用的对象那么就是全局对象window,相当于window.test();注意这里没有使用严格模式,如果使用严格模式,全局对象就是undefined,那么就会报错Uncaught TypeError:cannot read property "name" of underfined

在举个栗子:

var name = "outerName";
var test = {
    name:"innerName",
    fn:function(){
        console.log(this.name); //innerName
    }
};
test.fn();
window.test.fn();

这里打出的是innerName,因为fn是test调用的

还有个略坑的栗子:

var name = "outerName";
var test = {
    name:null,
    fn:function(){
        console.log(this.name); //outerName
    }
};
var f = test.fn
f();

这里打出的outerName因为f并没有被调用,fn()仍然是window调用的

再看看这个栗子:

var name = "outerName";
function fn(){
    var name = "innnerName";
    innerFn();
    function innerFn(){
        console.log(this.name); //outerName
    }
};
fn();

这里打出的是outerName,因为仍然是window调用的

总结一下:
this的指向并不是在创建的时候就可以确定的,在ES5里面,this永远是指向最后调用它的那个对象。

改变this指向

那我们怎么才能改变this指向呢,总结一下

使用ES6的箭头函数

在函数内部使用_this=this;

使用call、apply、bind

new 实例化一个对象

继续看一个栗子:

var name = "outerName";
var test = {
    name:"mm",
    fn1:function(){
        console.log(this.name);
    },
    fn2:function(){
        setTimeout(function(){
            this.fn1(); 
        },0);
    }
};
test.fn2(); //this.fn1 is not a funtion

箭头函数
ES6中的箭头函数是可以避免ES5中的this的坑的,箭头函数始终指向定义时的this,而非执行时。
箭头函数中没有this绑定,必须通过查找作用域链来觉得其值,如果箭头函数被非箭头函数包含,那么this绑定的是最近一层非箭头函数的this,否则,this为undefined.
调整后的栗子:

var name = "outerName";
var test = {
    name:"mm",
    fn1:function(){
        console.log(this.name);
    },
    fn2:function(){
        setTimeout(() => {
            this.fn1(); 
        },0);
    }
};
test.fn2(); //mm

在函数内部使用_this = this
_this指的是test对象

var name = "outerName";
var test = {
    name:"mm",
    fn1:function(){
        console.log(this.name);
    },
    fn2:function(){
        var _this = this;
        setTimeout(function(){
            _this.fn1(); 
        },0);
    }
};
test.fn2(); //mm

使用call,apply,bind

var name = "outerName";
var test = {
    name:"mm",
    fn1:function(){
        console.log(this.name);
    },
    fn2:function(){
        setTimeout(function(){
            this.fn1(); 
        }.apply(test),0);
    }
};
test.fn2(); //mm
var name = "outerName";
var test = {
    name:"mm",
    fn1:function(){
        console.log(this.name);
    },
    fn2:function(){
        setTimeout(function(){
            this.fn1(); 
        }.call(test),0);
    }
};
test.fn2(); //mm
var name = "outerName";
var test = {
    name:"mm",
    fn1:function(){
        console.log(this.name);
    },
    fn2:function(){
        setTimeout(function(){
            this.fn1(); 
        }.bind(test)(),0);
    }
};
test.fn2(); //mm

具体有什么区别呢
看下MDN上的解释

apply
语法:
fun.apply(thisArg,[argsArray]);
参数
thisArg
在fun函数运行时指定的this值,需要注意的是,指定的this的值不一定是该函数执行时真正的this值,如果这个函数处于非严格模式下,则指定为null或undefined时会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象。
argsArray
一个数组或者类数组对象,其中数组原始将作为多带带的参数传给fun函数。如果该参数的值为null或undefined,则表示不需要传入任何参数,从ECMAScript5开始可以使用类数组对象。

call
语法
fun.call(thisArg,arg1,arg2,...)
参数
thisArg
同上apply
arg1,agr2,...
指定的参数列表

bind
语法
fun.bind(thisArg[,arg1[,arg2[,...]]])
参数
thisArg
当绑定函数被调用时,该参数会作为原函数运行时的this指向。当使用new操作符调用绑定函数时,该参数无效。
arg1,arg2,...
当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。

在总结一下:
apply,call,bind都是用来改变函数的this对象的指向;
第一个参数都是this要指向的对象,也就是指定的上下文;
都可以利用后续参数传参;
apply,call是立即调用,bind是返回对应函数,需要手动调用。

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

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

相关文章

  • 浅谈-this

    摘要:回调函数中调用在回调函数中一般有两种情况回调函数为匿名函数时,回调函数的会指向,需要对回调函数。回调函数为箭头函数时,回调函数的会指向他的直接上层。 浅谈-this this简单而又神秘,使用场景多变而又复杂,这造就了它成为了初级javascript开发人员不愿接触的东西,高级javascript都想探究的东西。文本亦是对this的致敬。 this是什么? this是当前执行环境...

    archieyang 评论0 收藏0
  • 浅谈call()、apply()、bind()方法

    摘要:函数调用方法一般我们是这样调用函数的和现在我们说一说方法和方法。他们都是调用一个对象的方法,以另一个对象替换当前对象。例如方法在上面的例子中,,意思就是用来替换。和方法比较类似,其作用都是改变上下文的。 call(), apply(), bind() 函数调用方法 一般我们是这样调用函数的: function add(x){ console.log(x) } add(2)//2...

    zhangrxiang 评论0 收藏0
  • 浅谈 javascriptthis绑定问题

    摘要:绑定使用方式进行调用函数时,会发生构造函数的调用。先上图,然后根据文字阅读使用调用函数之后,该函数才作为构造函数进行调用,构造一个全新的对象赋值给,而对象的指向了的对象,的对象有一个属性指向的构造函数这个就是的原型链,也是的特性。 javascript语言是在运行时前即进行编译的,而this的绑定也是在运行时进行绑定的。也就是说,this实际上是在函数被调用时候发生绑定的,它指向什么完...

    duan199226 评论0 收藏0
  • call,apply and bind in JavaScript

    摘要:文章尽量使用大量实例进行讲解,它们的使用场景。在严格模式下,函数被调用后,里面的默认是后面通过调用函数上的和方法,该变指向,函数里面的指向。利用,可以传入外层的上下文。同样适用的还有,里面的对象,它也是一种类数组对象。 call,apply and bind in JavaScript 在ECMAScript中,每个函数都包含两个继承而来的方法:apply() 和 call(),这两个...

    JohnLui 评论0 收藏0
  • js基础深入浅出

    摘要:当多个事件触发的时候,会把异步事件依次的放入里等同步事件执行完之后,再去队列里一个个执行拾遗常用方法总结面试的信心来源于过硬的基础参考高级程序设计你所不知道的深入浅出知识点思维导图经典实例总结那些剪不断理还乱的关系 持续不断更新。。。 基本类型和引用类型 vue props | Primitive vs Reference Types 基本类型和字面值之间的区别 基本类型和字面值相等,...

    phodal 评论0 收藏0

发表评论

0条评论

Lemon_95

|高级讲师

TA的文章

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