一句话理解javascript的this指向

js中的this指向,总是一个让人困扰的问题,其实this的指向问题只需要理解这句话:this总是指向当前函数的所有者(调用者),可能说完这句话,很多人都是各种不认同,肯定有人说构造函数this指向实例,call(),new都可以改变this的指向。其实call或者new都是遵循这句话的,只是他们各自都隐藏了他们的执行过程而已。甚至有人说,在闭包中,this的指向会很奇怪,感觉在闭包中this就是居无定所般的存在。

那么我们开始分析this的指向把:

 
 
var name = 'the window';

function get_name(){
    console.log(this.name);
}
get_name();
window.get_name();

上面的代码,首先定义了window的name属性为‘the window’,还定义了函数get_name,函数打印this.name。此时都是window调用get_name。一句话:this总是指向当前函数的所有者(调用者)


代码继续往下走:

var name = 'the window';

function get_name(){
    console.log(this.name);
}
get_name();
window.get_name();// the window

var obj = {
    name:'the obj'
}

obj.fn_name = get_name;
obj.fn_name();// the obj

定义了一个新的obj对象,这个对象拥有name属性,并且值是‘the obj’,对象的动态特性,给obj添加了一个fn_namede 方法,并且这个方法也获得了get_name函数的指针:通过obj调用了fn_name所以打印出的结果是the obj;


3继续看添加的代码3:

//1
var name = 'the window';

function get_name(){
    console.log(this.name);
}
get_name();
window.get_name();// the window
// 2
var obj = {
    name:'the obj'
}

obj.fn_name = get_name;
obj.fn_name();// the obj
// 3
var person = {
    name:'张飞龙'
}
get_name.call(person); // 张飞龙
obj.fn_name.call(person);// 张飞龙 

第3部分第代码,从新定义了一个person对象,这个对象的name属性为‘张飞龙’,他并没有什么方法,但是我们通过call调用了get_name函数和obj.fn_name方法。其实这个两个函数都是同一个函数,并且都是通过person调用的,所以都打印张飞龙。



再来看看再构造函数中的this;

function Person(){
    this.name = '雷锋';
    console.log(this)
    this.say_name = function(){
        console.log(this.name)
    }
}
// 1
Person();//window对象
console.log(window.name);//雷锋
window.say_name()//雷锋

在还没有使用new的时候Person就是一个普通的函数。其实这和上面是一样的。


虽然是构造函数,其实在我眼里他还是个普通函数一样,只是new关键字的作用比较隐秘,发生的事情没有给我们看到而已

function Person(){
    this.name = '雷锋';
    console.log(this)
    this.say_name = function(){
        console.log(this.name)
    }
}

var person1 = new Person();//person1
console.log(person1);//person1
person1.say_name();// 雷锋

这个时候我们看到打印台的结果,会认为第一个打印的person1和第二个打印的person1不是同一个,其实是同一个,只是第一个打印是Person内部的console.log(this),而执行这一句的时候,下面的这句this.say_name并未执行,此时的this(new 出来的)并没有来得及添加say_name方法,我还是那么一相情愿的认为这个Person函数示例话对象时,是因为示例对象调用了Person函数,this才指向实例对象的,并且new关键字确实在他内部隐藏了以下的四部操作

// var person  ={};
// person.__proto__ = Person.prototype;
// Person.call(person);
// return person;

所以归结到底还是那句话。this的指向就是当前函数的调用对象。

最后我们再探讨以下闭包中的this;

var age = 24;

var person = {
    age:34,
    get_age:function(){

        return function(){
            return this.age;
        };
    }
};

var get_age1 = person.get_age()// get_age1的指针指向闭包中的匿名函数
console.log(get_age1());// 24 相当于window.匿名函数

我们只需要看this的函数的调用者是谁,接下来的这一句迷惑性就比较大了。

var person = {
    age:34,
    get_age:function(){

        return function(){
            return this.age;
        };
    }
};

var get_age1 = person.get_age()// get_age1的指针指向闭包中的匿名函数
console.log(get_age1());// 24 相当于window.匿名函数

console.log(person.get_age()())//这一大坨其实还只是得到了匿名函数


一眼看去最后一句的person.get_age()()这一句好像是在对象对函数的调用,其实这么调用返回的其实还是只是那个匿名函数。还是相当于window.匿名函数。因为person.get_age()它返回的其实仅仅是匿名函数,再来一个小括号就是匿名函数调用。如果这里还没明白的话,我继续往下写:

var age = 24;

var person = {
    age:34,
    get_age:function(){

        return function(){
            return this.age;
        };
    }
};

var get_age1 = person.get_age()// get_age1的指针指向闭包中的匿名函数
console.log(get_age1());// 24 相当于window.匿名函数

console.log(person.get_age()())//这一大坨其实还只是得到了匿名函数

var new_person = {
    age:44
}
new_person.get_a = person.get_age()//new_person.get_a就是那个匿名函数
console.log(new_person.get_a())//这里的调用才是真真的对象调用方法,或者说此时的this才是new_person的调用人

最后两句无非就是把匿名函数拿到手,并且给这个新person的方法赋值,回到最开始说的一句话,this指向当前函数的调用者。


最后我再说一句话,假传万卷书,真传一句话。









猜你喜欢

转载自blog.csdn.net/feilzhang/article/details/80576532