this指向浅析

作者: Miaoz0070 | 来源:发表于2020-06-01 14:48 被阅读0次

在开发过程中,使用this总会出现问题,时不时的会出现获取不到自己想要的对象和值,只要写js就必然要弄懂this指向问题。最近总结了下this指向问题,记录下来,方便之后巩固学习,也分享给大家希望能有所帮助。

  • 常见的window方法:alter,document,setTimeout,setInterval,一般使用都不会window.xx,而直接使用xx。如果this指向性是window的话,也可以使用this.xx。

  • use strict:严格模式,在脚本或函数的头部添加 "use strict"; 表达式来声明。指令只允许出现在脚本或函数的开头。
    在“use strict”严格模式下,没有直接的挂载者(或称调用者)的函数中this是指向window。在“use strict”严格模式下,没有直接的挂载者的话,this默认为undefined。以下都是在非严格模式下讨论。

  • 普通函数this指向:
    this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this指向的是window;当函数被作为某个对象的方法调用时,this就等于那个对象。
    1.总是代表着它的直接调用者,如obj.fn,fn里的最外层this就是指向obj
    2.默认情况下,没有直接调用者,this指向window,严格模式下(设置了'use strict'),this为undefined
    3.call,apply,bind改变this指向
    call: 第一个参数是this的指向,后面传入的是一个参数列表。当第一个参数为null、undefined的时候,默认指向window。如:xx.call(obj, 'xx', 'xx2', 'xx3')
    apply: 方法接收两个参数,第一个参数是this的指向,第二个参数是一个参数数组。当第一个参数为null、undefined的时候,默认指向window。如:xx.apply(obj, ['xx', 'xx2', 'xx3'])
    bind :call 方法很相似,第一个参数是this的指向,从第二个参数开始是接收的参数列表。区别在于bind方法返回值是函数以及bind接收的参数列表的使用。低版本浏览器没有该方法,需要自己手动实现.
    三者相似之处:
    1、都是用来改变函数的this对象的指向的。
    2、第一个参数都是this要指向的对象。
    3、都可以利用后续参数传参。
    区别:
    call和apply都是对函数的直接调用,而bind方法返回的仍然是一个函数,因此后面还需要()来进行调用才可以
    1.call和apply功能几乎一致,唯一的区别就是传参的方式
    2.call和apply的第一个参数如果为null或者undefined,那么this指向window
    3.call和apply的第一个参数如果为值类型的数据,那么会将这个值类型的数据,转换成其对应的引用类型的数据,然后再将this指向这个引用类型的数据
    4.call和apply立即执行这个函数,bind方法可以让对应的函数想什么时候调就什么时候调用,并且可以将参数在执行的时候添加,这是它们的区别,根据自己的实际情况来选择使用。
    5.当参数的个数确定的情况下可以使用call;当参数的个数不确定的情况下可以使用apply

  • 箭头函数改变this指向
    箭头函数的this定义:箭头函数的this是在定义函数时绑定的,不是在执行过程中绑定的。简单的说,函数在定义时,this就继承了定义函数的对象。这会很好的解决匿名函数和setTimeout和setInterval的this指向问题。我们不用再去给其用that变量存储this。
    1.默认指向定义它时,所处上下文的对象的this指向。即ES6箭头函数里this的指向就是上下文里对象this指向,没有上下文对象,this就指向window。
    2.即使是call,apply,bind等方法也不能改变箭头函数this的指向。
    3.看箭头函数定义的环境是什么 (找上一个 {})。
    4.定义环境执行时 this指向谁,箭头函数的 this就指向谁。
    5.箭头函数的this在定义的时候就确定,逐级向上查找找到最近的函数作用域的this。
    6.匿名函数没有直接调用者,this指向window。

  • 场景
    场景1:

function a(){
    var user = "xx";
    console.log(this.user); //undefined,window全局中没有定义user,所以是undefined
    console.log(this); //Window
}
a();

this最终指向的是调用它的对象,这里的函数a是,window调用。

场景2:

var a = {
    user:"xx",
    fn:function(){
        console.log(this.user);  //xx
    }
}
a.fn();

这里的fn是a在调用,所以fn中的this指向就是指向对象a。强调:this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁。

场景3:

var obj = {
    a:1,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); //12
        }
    }
}
o.b.fn();

场景1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window,这里需要说明的是在js的严格版中this指向的不是window。
场景2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。
场景3:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象。

var obj = {
    a:1,
    b:{
        // a:12, 注释掉
        fn:function(){
            console.log(this.a); //undefined
        }
    }
}
o.b.fn();

我们对象b中没有属性a,但是this指向还是对象b,因为this只会指向它的上一级对象,不管这个对象中有没有this要的东西。

场景4(特殊情况):

var obj = {
    a:1,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); //undefined
            console.log(this); //window
        }
    }
}
var s = obj.b.fn;
s();

这种情况this指向的是window,因为具体执行调用方法是在s()执行即window.s(),之前的var s = obj.b.fn;只是被引用,却没有执行调用。
this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的,场景4中虽然函数fn是被对象obj所引用,但是在将fn赋值给变量j的时候并没有执行所以最终指向是window,场景3是不一样的,场景3是直接执行了fn。

场景5(特殊情况):
如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。

//1.1
function fn()  
{  
    this.user = 'xx';  
    return {};  
}
var a = new fn;  
console.log(a.user); //undefined,this指向返回的对象。
//1.2
function fn()  
{  
    this.user = 'xx';  
    return function(){};
}
var a = new fn;  
console.log(a.user); //undefined,,this指向返回的对象。
//2.1
function fn()  
{  
    this.user = 'xx';  
    return 1;
}
var a = new fn;  
console.log(a.user); //xx,this指向实例a。
//2.2
function fn()  
{  
    this.user = 'xx';  
    return undefined;
}
var a = new fn;  
console.log(a.user); //xx,this指向实例a。
//2.3
function fn()  
{  
    this.user = 'xx';  
    return undefined;
}
var a = new fn;  
console.log(a); //fn {user: "xxx"}
//2.4null比较特殊,虽然null也是对象,但是在这里this还是指向那个函数的实例。
function fn()  
{  
    this.user = 'xx';  
    return null;
}
var a = new fn;  
console.log(a.user); //xx

场景6构造函数this:

function Fn(){
    this.user = "xx";
}
var a = new Fn();
console.log(a.user); //xx

为什么this会指向a?首先new关键字会创建一个空的对象,然内部机制会将this指向这个空对象,函数内部的this就会被这个空的对象替代。

this指向有很多种情况,需要在实际开发中自己去理解。

相关文章

网友评论

    本文标题:this指向浅析

    本文链接:https://www.haomeiwen.com/subject/gvaqohtx.html