浅谈javascirt this机制

                                             浅谈javascirpt this机制

       JS中的this到底是谁无疑是困扰很多新手的问题,在我们平时的编程中,很难绕开this的使用,它可以极大的方便我们编程。其实当我们熟悉了this的绑定规则之后我们可以很轻松的驾驭它。这里我们就来探讨一下this的绑定规则。  

       首先我们要知道什么是this,我们其实可以把this当作成一个对象,它是函数执行时动态添加的,所以我们写函数时也不知道this是谁,只有他执行是才知道,但是它是谁到底也还是我们控制的。

一.绑定规则

1 .构造函数绑定

在构造函数中,我们可以理解成我们在构造函数顶部创建了一个this对象 然后给this添加属性(这里只是比喻,内部的机制远不

止此)

function You(name,age) {
    var this = new Object();//隐形的假传看不见!)
    this.name = name;//this添加属性name
    this.age = age//this添加属性age
    return this//隐形的假传看不见!) //将this返回(这只是为了让我们更好理解,内部处理不止如此)
} 
        这是一个You构造函数,在函数内部我们创建了一个this对象,并给它添加了name 和 age 属性在分别赋值,这和我们平时给对

象添加属性的形式是一样的,当我们使用new操作符,就会将这个this返回(再次强调只为更好理解)。

function You(name,age) {
    this.name = name;
    this.age = age
}
var person = new You("jack","20");
console.log(person.name);//"jack
console.log(person.age);//"20"
        这里new使You返回了this对象,创建了一个实例并赋值给person。这里我们要注意一个点,就是构造函数内部使用了this,就不要

出现return语句,因为我们用new操作符实例对象会隐式的返回this对象,如果我们在构造函数内部使用了returen语句 new操作符将

不在返回this,而是返回你定义的那个return语句。

function You(name,age) {
    this.name = name;
    this.age = age;
    return {
        name:"haha",
        age:"100"
    }
}
var person = new You("jack","20");
console.log(person.name);// haha
console.log(person.age);// 100
        这里可以看到如果我们在构造函数内部使用了return,那么new将返回这个return之后的内容而不是this。      

当然这这是构造函数中的运用,我们平时运用它的地方远不止此!我们经常在方法中使用this,可以根据动态生成this更好的访问

对象属性,让我们的代码更“先进”。

2.普通函数绑定

①默认绑定

那我们平时经常会在普通的函数中使用this,那么在普通函数运行中this也会绑定,这是它会变成什么呢?来看第一个例子
var name = "windows";
function tom() {
    var name = "tom";
    function say() {
        console.log(this.name)
    }
}
say();//"windows"
咦!这里为啥那么是windows 我刚开是学的时候十分困惑 , 我们觉得 this绑定在tom的作用域才合理,因为say在tom中定义的。有人会说虽然在tom中定义但是实在全局作用域下运行的,this是动态绑定的所以是windows。那我们再看下面这个例子
var name = "windows";在
function tom() {
    var name = "tom";
    var say = function () {
        console.log(this.name)
    };
    say()
}
tom();//windows  
         我当时刚接触的时候十分困惑,因为say在Tom内部执行,this不因该绑定tom的执行环境嘛,为什么还是windows?后来得知这是设计上的失误(内心崩溃)。所以函数平常的执行,无任何修饰,this全是默认绑定在windows上。这一点我们当成概念记住,无从解释。我们就记得函数执行默认就是把this绑定给windows。

②隐式绑定

         我们平时还会用到”对象.方法“的方式访问函数。这时this就会发生变化了这里的this会指向调用它的那个对象。例如 

function say() {
    console.log(this.name)
}
var jack={
    name:"jack",
    say:say
};
jack.say();//jack
         这里this就会隐式的绑定给调用方法的那个对象,只会在调用它的那个对象里找name,如果没有就会返回undefined,无论windows中有没有绑定,可以说此时this的上下文就只在这个对象之中。

③强制绑定

         我们知道函数都有call和apply方法,这两个函数的第一个参数接收一个对象,当函数调用这两个方法时就会将this绑定给这个对象。 

var name ="windows";
function say() {
    console.log(this.name)
}
var jack={
    name:'jack'
};
say.call(jack);//jack
         这里的this就会绑定到jack对象上面,因为call方法就是绑定this的值,从而让say中的this绑定到jack上,而不是默认的windows对象上面。

        以上就是全部的this绑定规则,这时我们问题就来了,既然有这么多绑定那么他们同时出现怎么算。这就要进行优先级排序了。

二 优先级比较

        那么 默认绑定 隐式绑定 强制绑定的优先级是什么呢?同时出现this会绑定谁呢?
 前面我们已经看到了 隐式绑定和强制绑定的优先级都是大于默认绑定的,这里我们就只需要判断它们俩的优先级,还是看代码。

var name ="windows";
var jack={
    name:'jack',
    say:say
};
var tom={
    name:"tom"
};
jack.say.call(tom);//tom
         一个例子胜过千言万语,这个例子说明了一切。这里同时有三种绑定,默认全局有name="windows",调用时通过jack.say的方调调用(隐式绑定),有通过函数的call方法强制绑定tom 最后的就结果是tom。

         这里可以看出强制绑定的优先级是高于隐式绑定的。所有优先级强制绑定 > 隐式绑定 > 默认绑定


三 ES6中的箭头函数

         上面的都是ES5中的this绑定规则,当然ES6中也是如此,但是ES6中新出现了一种箭头函数。
const say = (name)=>{
    console.log(name)
};
say("jack")
         这就是箭头函数,具体用法可以看ES6入门,哪里有详细解答,这里我们只讨论其中的this。
我们知道函数中this默认是绑定到windows上的。可是在箭头函数中就不一样了。
let name = "windows";
function foo() {
    setTimeout(() => {
        console.log( this.name);
}, 50);
}
foo.call({ name: "foo" });//"foo"
       我们看到在foo函数中定义了一个定时器,里面有一个箭头函数,我们知道函数默认都是绑定到windows上的那么,定时器执行,应该将其中的this绑定到windows上,从而输出“windows"。但是最后结果是"foo"。call让foo的this指向了{name:"foo"}对象,此时箭头函数里的this也指向了这个对象(因为输出是"foo")。
       这里我们就可以看出来了:箭头函数的this不在遵循以前的函数绑定,而是绑定在定义时所在的对象。他是固定的。以前的this是动态生成,而箭头函数中的this在我们书写的时候就决定他的指向。

以上就是我对this的理解,如有不对请及时告知,谢谢
       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值