zoukankan      html  css  js  c++  java
  • this总结

    this总结,mark一下:

    Object中的this:

    Object方法中的this,指向的就是该对象,即谁调用this就指向谁,与C#等服务器语言的思想比较一致。

     1 let
     2     demo = {
     3         name: "dqhan",
     4         action: function () {
     5             console.log(this); //{name: "dqhan", action: ƒ}
     6             (function () {
     7                 console.log(this);//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
     8                 // "use strict";
     9                 // console.log(this);//undefined
    10             })();
    11         }
    12     };
    13 demo.action();

    demo对象调用action,action中的this指向的就是demo,action内部的自执行函数this则指向的是window,严格模式下为undefined。可以写个深层次的demo来看下会不会影响this的指向

     1 let
     2     demo = {
     3         name: "dqhan",
     4         action: function () {
     5             console.log(this) //{name: "dqhan", action: ƒ, innerDemo: {…}}
     6         },
     7         innerDemo: {
     8             name: 'innerDqhan',
     9             action: function () {
    10                 console.log(this)//{name: "innerDqhan", action: ƒ}
    11             }
    12         }
    13     };
    14 demo.action();
    15 demo.innerDemo.action();

    事实证明不会影响this的指向,这种方式的定义以及调用不参与原型链,不涉及this指向改变的问题。

    函数中的this:

    匿名函数中,函数体内的this指向为window,严格模式下为undefined。

    1 function demo(){
    2     console.log(this);//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
    3     // "use strict"
    4     // console.log(this);//undefined
    5 }
    6 demo();
    1 foo = 'outer'
    2 function demo() {
    3     this.foo = 'inner';
    4     // "use strict";
    5     // this.foo = 'inner';//error
    6 }
    7 console.log(foo);//outer
    8 demo();
    9 console.log(foo);//inner

    foo在不加var,let(ES6)下自动挂载window下,调用demo后在函数内部将foo重新赋值。严格开发下this为undefined报错。

    构造函数中的this:

    提到this常常想到的是构造函数,写个简单的demo如下

     1 function Demo() {
     2     this.name = "dqhan";
     3     this.action = function () {
     4         console.log(this)//Demo {name: "dqhan", action: ƒ}
     5     };
     6 };
     7 
     8 let
     9     demo = new Demo();
    10 demo.action();
    11 console.log(demo.name);//dqhan

    调用demo内的action,action中的this指向构造函数的实例化对象,原因是什么呢?这里需要了解一下let demo = new demo();到底发生了什么。

    1 //action1
    2 let
    3     demo = new Demo();
    4 //action2
    5 let
    6     demo = {};
    7 demo.__proto__ = Demo.prototype;
    8 Demo.call(demo);

    js中new一个实例化对象的过程等价于action2的代码,最后一步通过call方法(apply,bind)将demo对象中的this传递到了Demo构造函数中,从而将构造函数中没有定义在原型中的属性与方法都定义到了demo 对象中,这就是为什么构造函数中的this会是实例化对象的原因。另外我们可以将属性或者方法都定义在原型中

     1 function Demo() {
     2     this.name = "dqhan";
     3 };
     4 Demo.prototype.action = function () {
     5     console.log(this)//Demo {name: "dqhan", action: ƒ}
     6 };
     7 
     8 let
     9     demo = new Demo();
    10 console.log(demo.name);//dqhan

    我们都清楚,构造函数类似于一个简单工厂模式,我们可以通过一个构造函数生成很多其他对象,我们将属性或者方法定义在原型中,这样可以达到原型共享的目的。

     1 function Demo() {
     2     this.name = "dqhan";
     3 };
     4 Demo.prototype.action = function () {
     5     console.log(this)//Demo {name: "dqhan", action: ƒ}
     6 };
     7 let
     8     demo = new Demo(),
     9     demo1 = new Demo(),
    10     demo2 = new Demo();
    11 demo.__proto__ === demo1.__proto__;//true
    12 demo1.__proto__ === demo2.__proto__;//true

    当对象非常多的是时候,可以节约内存。

    当函数内嵌套匿名函数

     1 function Demo() {
     2     this.name = "dqhan";
     3 };
     4 Demo.prototype.action = function () {
     5     console.log(this);//Demo {name: "dqhan", action: ƒ}
     6     (function () {
     7         console.log(this);//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
     8         // "use strict";
     9         // console.log(this)//undefined
    10     })();
    11 };
    12 let
    13     demo = new Demo();
    14 demo.action();

     定义在构造函数内的方法在传递的时候,实例化对象不会跟着一起传过去

     1 function Demo() {
     2     this.name = "dqhan";
     3 };
     4 Demo.prototype.action = function () {
     5     console.log(this);
     6     
     7 };
     8 function foo(method){
     9     method();
    10 };
    11 let
    12     demo = new Demo();
    13 foo(demo.action);//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
     1 function Demo() {
     2     this.name = "dqhan";
     3 };
     4 Demo.prototype.action = function (method) {
     5     console.log(this);
     6     method();
     7 };
     8 Demo.prototype.actionCallBack = function () {
     9     console.log(this);
    10 }
    11 let
    12     demo = new Demo();
    13 demo.action(demo.actionCallBack);
    14 //Demo {name: "dqhan"}
    15 //Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}

    这两种情况都是将实例化对象中的方法当成参数进行传递。但是在执行函数中,this的上下文已经发生改变。解决方式可以通过bind,apply,call等改变上下文的方式。

     1 function Demo() {
     2     this.name = "dqhan";
     3 };
     4 Demo.prototype.action = function (method) {
     5     console.log(this);
     6     method()
     7 };
     8 Demo.prototype.actionCallBack = function () {
     9     console.log(this);
    10 }
    11 let
    12     demo = new Demo();
    13 demo.action(demo.actionCallBack.bind(demo));
    14 // Demo {name: "dqhan"}
    15 // Demo {name: "dqhan"}
     1 function Demo() {
     2     this.name = "dqhan";
     3 };
     4 Demo.prototype.action = function () {
     5     console.log(this);
     6     (function () {
     7         console.log(this);
     8     }).apply(this);
     9 };
    10 let
    11     demo = new Demo();
    12 demo.action();
    13 // Demo {name: "dqhan"}
    14 // Demo {name: "dqhan"}

    setTimeout中的延迟函数中this

     1 let
     2     obj = {
     3         timerAction: function () {
     4             console.log(this);
     5         }
     6     };
     7 function foo(method) {
     8     method();
     9 };
    10 obj.timerAction();
    11 foo(obj.timerAction);
    12 setTimeout(obj.timerAction, 0);
    13 // {timerAction: ƒ}
    14 // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
    15 // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}

    之前看过一篇关于setTimeout使用时延迟函数自动挂载window上。今天总结了一下,发现这种方式个人觉得可以理解成,以函数当做参数进行传递this都是传递不过去的。如果简单的写一个函数,那么问题就更不存在了,匿名函数本身就是挂载window下,没有争议了。

  • 相关阅读:
    人工智能_智能家居:数据采集与数据标注
    人工智能_智能安防:数据采集与数据标注
    AI行业精选日报_人工智能(01·02)
    人工智能:智能驾驶训练数据,数据采集与数据标注
    AI行业精选日报_人工智能(12·31)
    撕掉旧标签,华为要与运营商联手破局云计算
    移动云:三年投资千亿元 打造中国第一阵营云业务
    腾讯的下一个十年,云计算如何成为新增长引擎
    云计算进入下半场,这家容器云公司将如何打造中台战略? | 爱分析调研
    每日经济新闻:腾讯云单季增速超阿里云 仍“前有狼后有虎”
  • 原文地址:https://www.cnblogs.com/moran1992/p/8515711.html
Copyright © 2011-2022 走看看