位置:首页 > web前端 > javascript

轻松理解javascript中的this指向

dearweb 发布:2021-05-08 16:54:51阅读:

在javascript中,this的指向并不是在函数定义的时候确定的,而是在其被调用的时候确定的。也就是说,函数的调用方式决定了this指向。记住:this 就是一个指针,指向我们调用函数的对象。 

在此将javascript中this的调用方式分为以下几种:

直接调用:直接调用是指通过 funName(…) 这种方式调用。此时,函数内部的this指向全局变量。

function fnFoo() {
    console.log(this === global);
}
fnFoo(); //true

使用bind函数改变外层函数的作用域,然后在内层直接调用,其this指向依然是全局变量:

function fnFoo() {
    console.log(this === global);
}

function fnFooTo() {
    fnFoo();
};
var fnFooTo2= fnFoo.bind({}); //改变foo1函数的作用域
fnFooTo2(); //true 依然指向全局变量

函数表达式,将一个函数赋值给一个变量,然后通过直接调用的调用方式调用此函数,其this指向依然是全局变量:

let object = {
    fnFoo: function(){
        console.log(this === object );   //false
        console.log(this === global);  //true
    }}
let fn = object .fnFoo
fn();

方法调用: 

方法调用是指通过对象来调用其方法函数,类似object.fnFoo(…)的调用方式。此时,this指向调用该方法的对象,注意,是最终调用该方法的对象。

var object= {
    fnFoo1: function(){
        console.log(this === obj);
    }}
object.fnFoo2 = function() {
    console.log(this === obj);
}
function fnFoo3() {
    console.log(this === obj);
}
object.fnFoo3 = fnFoo3();
object.fnFoo1(); //true
object.fnFoo2(); //true
object.fnFoo3(); //true

new 调用: 

在es5中,通过 new Constructor() 的形式调用一个构造函数,会创建这个构造函数实例,而这个实例的this指向创建的这个实例。如下例所示,在构造函数内部使用this.name并没有改变全局变量name的值。

var name = "全局";function Person(name){
    this.name = name;
}
var p = new Person("局部");
console.log(p.name);
console.log(name);

上述三种情况是常见的调用方式,以下还有一些特殊的调用方式:如bind、call、apply以及es6中箭头函数。

bind函数对this的影响

bind函数用于绑定this的指向,并且返回一个绑定函数,此函数绑定了this指向,注意:绑定函数的this指向将不可再次更改。

var obj = {};function foo1() {
    console.log(this === obj);
}
foo1(); //false  此时属于上述直接调用的方式,因此其this指向global
var foo2 = foo1.bind(obj);
foo2(); //true 绑定函数的this指向其绑定的对象/**
 * 注意:绑定函数的this指向不可更改 */
var foo3 = foo2.bind({'a': 1});
foo3(); //true 
foo2.apply({'a': 1}); //true 
foo2.call({'a': 1});  //true

apply和call对this指向的影响

apply和call亦可以用于改变this指向,并且返回执行结果。关于bind、apply和call的区别以及实现可以参考我之前发布的文章:《bind、call、apply的区别与实现》。需要注意的一点是:apply和call不可以改变绑定函数(使用bind返回的函数)的this指向。

var obj = {};function foo1() {
    console.log(this === obj);
}
var foo2 = foo1.bind({'a': 1});
/* 注意:此处并不是绑定函数,因此其返回值依然是ture,即apply改变其this指向。 */
foo1.apply(obj); //true
/* 注意:此处是绑定函数,因此不可再通过apply和call的形式改变其this指向。 */
foo2.apply(obj); //false

es6箭头函数中的this

箭头函数没有自己的this绑定,其使用的this是其直接父级函数的this。也就是说,箭头函数内部的this是由其直接外层函数(方法)决定的,而外层函数中的this是由其调用方式决定的。

const obj = {
    foo: function() {
        const inner = () => {
            console.log(this === obj);
        };
        inner();
    },
    far: function() {
        return () => {
            console.log(this === obj);
        }
    }}
/* inner()内的this是foo的this,其指向取决于foo的调用方式*/
obj.foo(); //true
var foo1 = obj.foo;foo1();//false 此时应该指向global
const far1 = obj.far();
far1();    //true
const far2 = obj.far;
far2()();  //false 此时应该指向global
24人点赞 返回栏目 提问 分享一波

小礼物走一波,支持作者

还没有人赞赏,支持一波吧

留言(问题紧急可添加微信 xxl18963067593) 评论仅代表网友个人 留言列表

暂无留言,快来抢沙发吧!

本刊热文
网友在读
手机扫码查看 手机扫码查看