this的用法详解

this是 JavaScript 语言的一个关键字

它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用

个人比较喜欢将this理解成上下文语境 既然是语境一定有主语 我们只需要关注 主语是谁就可以了,因为谁用了this 那么this肯定是指向谁的

this的特性

要注意的是,this的语境绝对不是在创建时决定的,而是函数运行是决定的,还是那句话,谁用了this指向谁
列举几个简单的例子容易理解

作为普通函数在全局环境中被调用

var x = 1;
function test() {
console.log(this.x);
}
test();  // 1

这个函数很容易理解,作为一个普通函数在全局中调用 此时this是指向全局 为什么这么说,其实很简单,因为这是我们的简写

var x = 1;
function test() {
console.log(this.x);
}
window.test()  // 1

这才是完整的写法,只是我们平时都会省略window,此时我们的方法是通过window使用的,好我们此时主语是window,那么我们就会在window下 寻找x 就找到了全局下的x 输出1,所以我们要知道方法一定是有人调用的,如果没人用那就是window爸爸在用了,所以匿名函数的this一定指向window了

再看一个例子
var x = 1;
function test() {
var y=6    
console.log(this.x);
console.log(this.y);
}
window.test();  // 1  undefined

同样的道理,此时y就显示了undefined 此处显示undefined 并不是说没有y,我们都知道var是存在变量提升的,因为js是从上到下解析,如果我们把y放在函数外

var x = 1;   
function test() {
console.log(this.x);
console.log(this.y);
}
var y=6    
window.test();  // 1  6

此时就能输出6了,因为此时的window.y是等于6的

var x = 1;  
function test() {     
console.log(this.x);
console.log(this.y);
}
window.test();  // 1
var y=6    

此时放在下面又变成undefined了,因为此时的window.y是undefined

在对象中使用例子

var x=2;
function test() {
console.log(this.x);
}

var obj = {};
obj.x = 1;
obj.m = test;

obj.m(); // 1

在对象中设置了俩个属性,一个是x,一个是m,此时obj就变成了

obj={
 x:1,
 m:function test(){
 console.log(this.x)
 }
}

此时方法前面有对象了,这个对象是obj,也就是说此时的语境是obj了,那么翻译一下就是obj在使用m方法了,那么this此时是被obj使用的,那么this就指向obj这个对象,也就是说此时this.x==obj.x,很显然打印1

构造函数中使用

所谓构造函数,就是通过这个函数,可以生成一个新对象。这时,this就指这个新对象。

     var name='mama';
     var age='18';
    function test(name,age) {
     this.name=name;
      this.age=age
    }
    var obj = new test('this','18');
    console.log(name,age) //mama  18
    console.log(obj.name,obj.age)  //this 18

其实我认为不需要解释了,很容易理解,谁调用此时的this指向谁,就会在谁的下面寻找属性

这里构造函数首字母要大写,不会报错但是是一种规范 额我是故意写这样的

再看一个构造函数的例子

    function Person (name) {
        console.log(this) // window
        this.name = name;
    }
    Person('inwe')
    //使用new
    function Person (name) {
        this.name = name
        console.log(this) //people
        that = this
    }
    var people
    console.log(that === people) //false
    var people = new Person('iwen')
    console.log(that === people) //true

前面两个函数好理解,第二个函数,我们将this赋值给that,看看对比
在构造实例之前,此时函数在全局下,属于window,那自然不等于people
构造实例之后this指向构造的实例,此时this就相当于是people这个实例了

强行改变this语境

使用apply call bind 三个方法强行改变this语境,详情用法可以百度一下,此处只介绍apply

apply()是函数的一个方法,作用是改变函数的调用对象。它的第一个参数就表示改变后的调用这个函数的对象。因此,这时this指的就是这第一个参数

    var x = 0;
    function test() {
     console.log(this.x);
    }

    var obj = {};
    obj.x = 1;
    obj.m = test;
    obj.m.apply() // 0
    obj.m.apply(obj); //1

apply()的参数为空时,默认调用全局对象。虽然是obj调用的方法,但是这时的运行结果为0,证明this指的是全局对象
最后一行又将this指向obj,输出1

从理论以及基础上面来讲 this并不难,谁调用this指向谁,当然还有很多复杂的情况,闭包啊原型链啊,但是万变不离其宗,谁用它就是指向谁,找几个笔试题我们可以分析一下

    var name = "caibaojian.com"; 
    var person = {
    name: "kang",
    pro: {
        name: "Michael",
        getName: function() {
        return this.name;
        }
    }
    };
    console.log(person.pro.getName()); // Michael
    var pepole = person.pro.getName;
    console.log(pepole()); // caibaojian.com

首先我们分析第一个 person.pro.getName()注意此处是有括号的
函数体加()=函数执行
此时相当于返回的就是this.name
好 谁用this指向谁,方法我们是person下的pro这个对象使用的,name此时就指向pro.name很简单
分析接下来这个 注意此时是= 在js中=是指右边赋值给左边
此时右边是函数体,它并没有执行,那么此时函数赋值给了people,此时people此时就相当于一个函数
注意了,people前面可是省略了window的 也就是说相当于是window.people(),所以他返回的是全局下的name

    'use strict';
    var name = "caibaojian.com"; 
    var person = {
    name: "kang",
    pro: {
        name: "Michael",
        getName: function() {
        return this.name;
        }
    }
    };
    console.log(person.pro.getName()); //  Michael
    var pepole = person.pro.getName;
    console.log(pepole()); // undefined

本来是不想复制这个的,其实这里为什么undefined 因为最上面设置了严格模式,而严格模式下没有默认的window全局对象,捎带的提个醒

    var name = "caibaojian.com",
        person = {
        name : "kang",
        getName : function(){
         return function(){
             return this.name;
         };
        }
        };

    console.log(person.getName()()); // caibaojian.com  

这道题目有点小恶心啊,一步步分析,先看getName()
注意此时它有括号,函数执行返回第一个return 也就是返回一个function
注意 坑来了 此时它又有一个() 又执行了 这其实就相当于一个匿名函数了
一定注意,函数加括号代表执行 匿名函数一定指向window 因为它不需要谁调用 它一打开页面就开始跑了 它已经疯了

    function a(xx){
        this.x=xx;
        return this
    };
    var x=a(5);
    var y=a(6);
    console.log(x.x); //undefined
    console.log(y.x); //6

这道题可以说是相当的变态,我尽量表达清楚意思
注意了这个函数,它return返回的是this 一个函数的最终结果一定是return
我们要知道,函数改变相应数据结构的同时,并不代表函数结果,只有return 才是函数的结果
那么第一个 var x=a(5) 我们不管发生了什么,我们可以确定此时x已经是window了
同样的道理 var y=a(6) 不管发生了什么 y此时就是window return this返回的就是window
接下来我们逐步分析,var x =window 这个应该没问题
注意 这里是高潮 var y=window 没毛病 但是y执行函数的时候 触发了 this.x=6(这步没看懂的再捋一下)
前面一个var x=a(5)返回的结果是window 就是说this.x=window,执行y的时候对x进行了覆盖
也就是说此时的this.x它是等于6 发现没有
到这里,问题就解决了,返回的最终结果就是console.log(6.x,window.x)
所以答案是undefined 6 是不是很变态

多做一些题目自然而然对于this有很好的掌握,不过最好是在你掌握了原型,闭包,预解析,ES6的情况下,这边顺带提一下,箭头函数 它的this指向函数的父函数,我们实际开发并没有这么复杂,但是这种题很考验我们的js功底

猜你喜欢

转载自blog.csdn.net/qq_26006661/article/details/83895794
今日推荐