微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

JavaScript 你真的了解this指向吗

前言

  终于开始写this指向了,相信这对很多JavaScript的学习者来说是一个非常恐怖的环节,个人认为也算是JavaScript中最难理解的一个知识点,this非常的方便但是在你不熟悉它的情况下可能会出现很多坑。

  本篇文章将带你充分了解this指向,用最精炼简短的语句阐述不同情况下的this指向。

详解this指向

window对象

  window一个全局的对象,里面存了很多方法

  当我们使用var进行变量命名时,变量名会存入到window对象中,以及当我们使用标准函数定义方法函数名也会存入window对象中。

<script>var username = "云崖";

        function show(){
                console.log("show...");
        };

        console.log(window.username);  // 云崖
        window.show();   show...
</script>

全局环境

  在全局环境中,this的指向就是window对象。

  但是我们一般不这么用。

<script>);
        };

        console.log(this.username);   云崖
        this.show();   show...
 依旧可以执行,代表全局环境下this就是window对象
         如果你不相信,可以打印它看看。

        console.log(this);    Window {parent: Window,opener: null,top: Window,length: 0,frames: Window,…}
</script>

普通函数

  非严格模式下,普通函数this的指向为window对象。

<script> "use strict"; // 在非严格模式下,普通函数中this的指向是window对象
 show() {

                console.log("show...");
                console.log( window

        };

        show()

</script>

  但是在严格模式下,普通函数this指向为undefined

<script>"use strict";  在严格模式下,普通函数中this指向为undefined
 undefined

        };

        show()

</script>

构造函数

  一个函数能被new时,该函数被称之为构造函数

  一般构造函数中包含属性方法函数中的上下文指向到实例对象。

  在构造函数中的this一般指向为当前对象。对于其方法而言this指向同样为当前对象。

  你可以这么认为,在用Function定义类时,类中的方法指向当前类。

  这样是不是好理解多了?

<script>"use strict"; 

        function User(username) {   在没有class语法出现之前,这种构造函数我们通常会将它当做类来看待。
this.username = username;   可以称之为类属性

                console.log( User {username: "云崖"}  代表指向当前对象
this.show = function () {   可以称之为类方法

                        console.log( 云崖
                        console.log( {username: "云崖",show: ƒ}  代表指向当前对象
                }

        }

        let user = new User("云崖");
        user.show();

</script>

对象字面量

  在对象中的this指向即为当前对象,同样的在对象中的函数方法this指向也是当前对象本身。

  这与构造函数如出一辙。

<script>"use strict"; 

        let obj = {
                username:"云崖", 最终的key都会转为String类型,但是Symbol类型不会转换。

                show:function(){  这里也可以将show称作为方法,而username即为属性
this.username); 
                },}

        obj.show();

</script>

方法中的普通函数

  首先聊方法中的普通函数之前,要先知道什么情况下的函数常被称之为方法

  结合本章前面介绍的内容,以下环境中的函数将被称之为方法

  在构造函数中的函数可以将其称之为方法

  在对象中的字面量函数也可以将其称之为方法

  那么,在方法中的普通函数即是这样的:

  在构造函数中的函数中的函数可以称其为方法中的普通函数

  在对象中的字面量函数中的函数也可以将其称为方法中的普通函数

  有点绕哈,看代码你就懂了。

  方法中的普通函数this指向非严格模式下为window对象,严格模式下为undefined

  值得一提的是,对于大多数开发者而言,这么嵌套的情况很少使用。

<script>"use strict" User(username) { 

                this.username = username; 

                 方法
function inner() {   普通函数
                                console.log( 严格模式:undefined,非严格模式:window
                        };

                        inner();  方法中定义一个函数调用

                }

        }

        let user = );
        user.show();

</script>
<script>"use strict"function(){  function inner(){  方法中的普通函数改变this指向

  那么,怎么改变方法中普通函数this指向呢?

  非常简单。使用一个常量将方法this赋值并传递给其中的普通即可。

<script>"use strict"
                        let self = this;   这个this指向的当前对象,即User
function inner(self) {   普通函数
                                console.log(self);  方法内的普通函数中使用self即可
                        };

                        inner(self);   我们将self传递进去
;

        let obj = {
                username: "云崖",1)">
                show:  这个this指向的当前对象,即obj
方法内的普通函数中使用self即可
方法中的箭头函数

  箭头函数这玩意儿没有this指向,你可以理解为它始终会与外层定义自己的函数共同使用一个this,在大多数情况下是会如此,但是少部分情况会除外,比如在事件的回调函数中,这个在下面会有举例。

  方法中的箭头函数this指向始终会与定义自己的函数共同使用一个this

<script>"use strict" User(username) {

                 username;

                 指向 User

                        let inner = () =>   console.log( 箭头函数,与定义自己的外层指向同一this,即User

                        inner();  );
        user.show();

</script>

事件普通函数

  事件函数是指某一动作方式后所调用的回调函数,如果是普通函数那么this指向即为事件源本身。

<script>"use strict";

        let div = document.querySelector("div");

        div.onclick =  (event) { 

                console.log(event);   事件
 div标签,即为事件源本身,DOM对象
         }

</script>

事件箭头函数

  事件的回调函数如果箭头函数,那么this指向即为window,一句话,向上找,看在哪个环境下定义了这个箭头函数

  所以我们尽量不要去用箭头函数作为事件的回调函数

<script>"use strict");

         由于是在全局定义的,所以此时的this即为window,如果是在方法中定义的事件箭头函数则this指向
         就不是window了

        div.onclick = event => { 

                console.log(event);   Window 
         }

</script>

事件箭头函数获取事件源

  如果想在事件箭头函数获取事件源,那就不使用window了。用event参数中的一个target属性即可找到事件源。

<script>"use strict");

        div.onclick = event => { 

                console.log(event.target);   事件源DOM对象
         }

</script>

改变this指向

call方法

  通过call()方法,让原本函数this发生改变,如下实例我们可以在user函数中使用this去给对象obj进行添加属性

  参数1:新的this指向对象

  其他参数:函数中本来的传递值

  特点:立即执行

<script>"use strict" user(name,age) {
                this.name = name; 
                this.age = age;
                console.log(this);
        };

        let obj = {};

        user.call(obj,"云崖",18);

        console.log(obj.name);  云崖
        console.log(obj.age);  18
</script>

apply方法

  call()方法唯一不同的地方在于参数传递,其他都一样。

  参数1:新的this指向对象

  参数2:函数中本来的传递值,请使用数组进行传递。

  特点:立即执行

<script>"use strict" {};

        user.apply(obj,["云崖",1)">]);

        console.log(obj.name);  18
</script>

bind方法

  方法最大的特点是具有复制特性而非立即执行,对于函数的参数传递可以有多种。

  但是我这里只介绍一种。

  参数传递:使用bind()方法时传递一个this指向即可

  特性:会返回一个新的函数

<script>"use strict" {};

         可以这么理解,使用bind()方法的第一步,告诉this指向谁,第二步,复制出新函数,第三步,新函数的this已经改变。其他地方与原函数相同。
        let new_func = user.bind(obj);  obj传递进去,返回一个函数,该新函数与user函数除了this指向不一样其他均相同。
        new_func("云崖",1)">)

        console.log(obj.name);  18
</script>

总结

  window对象 当前对象 上级this指向 事件源DOM对象 undefined
全局环境(不在函数中)        
普通函数 非严格模式:√       严格模式:√
构造函数        
对象        
构造函数中的方法        
对象中的字面量方法        
构造函数中的方法中的普通函数 非严格模式:√       严格模式:√
对象中的字面量方法中的普通函数 非严格模式:√       严格模式:√
构造函数中的方法中的箭头函数      
对象中的字面量方法中的箭头函数      
事件普通函数        
事件箭头函数 大概率是√,主要看上层的this指向      


 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐