资讯专栏INFORMATION COLUMN

js中this的“终极三问”

silvertheo / 460人阅读

摘要:是什么本质是一个绑定,在函数被调用时建立。它的指向是完全由函数被调用的调用点来决定的。因为函数的调用点在全局作用域,所以指向全局变量这里就是函数的调用点存在的意义在函数体内部指代函数当前的运行环境。从而实现干净的设计和更容易的复用。

this是什么?
this 本质是一个绑定, 在函数被调用时建立。它的指向是完全由函数被调用的调用点来决定的。

function baz() {
    console.log(this);//因为baz函数的调用点在全局作用域,所以this指向全局变量
}
baz();//这里就是baz函数的调用点

this 存在的意义
在函数体内部指代函数当前的运行环境。从而实现干净的 API 设计和更容易的复用。
this的使用

top-level scope

   1) In browsers, the top-level scope is the global scope. This means that within the browser var something will define a new global variable.In Node.js this is different. The top-level scope is not the global scope; var something inside a Node.js module will be local to that module. 
   2) 但是在Node REPL下,与浏览器的行为保持一致(timers除外)
       In browsers
           var that = this;
           setTimeout(function() {
             console.log(this);//window
           }, 0);
        Node REPL
           var that = this;
           setTimeout(function() {
             console.log(this);//Timeout {...}
           }, 0);   
       setInterval 结果相同

严格模式下

   指定的this不在被封装为对象,而且如果没有指定this,则this的值为undefined
   sloppy mode
       function foo() {
         console.log(this);
       }
       foo.apply("test"); //==>String {"test"}0: "t"1: "e"2: "s"3: "t"length: 4...[[PrimitiveValue]]: "test"
    strict mode    
       function foo() {
         "use strict";
         console.log(this);
       }
       foo.apply("test"); //==>test        

调用方法时没有明确对象,this指向全局对象

   sloppy mode
       In browsers,this指向window
           console.log(this);//window
       Node REPL, this指向global
           console.log(this);//global
   strict mode
       In browsers,this指向window
           "use strict";
           console.log(this);//window
       Node REPL, this指向global
           "use strict";
           console.log(this);//global            

匿名函数执行时当前对象是全局对象

   sloppy mode
       In browsers,
           (function() {
             console.log(this);//window
           })();
       Node REPL
           (function() {
             console.log(this);//global
           })(); 
   strict mode
       In browsers,
           (function() {
             "use strict";
             console.log(this);//undefined
           })();
       Node REPL
           (function() {
             "use strict";
             console.log(this);//undefined
           })(); 

强制一个函数调用使用某个特定对象作为 this 绑定,而不在这个对象上放置一个函数引用属性
就 this 绑定的角度讲,call(..) 和 apply(..) 是完全一样的
call

   function foo() {
     console.log(this.a);
   }
   var obj = {
     a: 2
   };
   foo.call(obj); //==>2 强制函数foo()的 this 指向 obj

apply

   function foo() {
     console.log(this.a);
   }
   var obj = {
     a: 2
   };
   foo.apply(obj); //==>2 强制函数foo()的 this 指向 obj     
    
bind 返回一个硬编码的新函数,它使用你指定的 this 环境来调用原本的函数
   function foo(something) {
     console.log(this.a, something);
     return this.a + something;
   }
   var obj = {
     a: 2
   };
   var a = 6;
   var bar = foo.bind(obj);//使用obj作为this环境调用foo()
   var b = bar(3); // 2 3
   console.log(b); // 5
   var test = bar.bind(window);//2 3 
   console.log(test(3)); // 5
   

传递 null 或 undefined 作为 call、apply 或 bind 的 this 绑定参数,那么这些值会被忽略掉。

   sloppy mode
       function foo() {
         console.log(this);
       }
       var obj = {};
       foo.call(null);//window or global
       foo.apply(null);//window or global
       var bar = foo.bind(null);
       console.log(bar());//window or global
    strict mode
       "use strict";
       function foo() {
         console.log(this);
       }
       var obj = {};
       foo.call(null);//null
       foo.apply(null);//null
       var bar = foo.bind(null);
       console.log(bar());//null        

new

   将新构建的对象被设置为函数调用的 this 绑定
   function foo(a) {
     console.log(this);
     this.a = a;
   }
   var bar = new foo(2);//构建了一个新的对象(foo {a: 2})并把这个新对象作为 foo(..) 调用的 this
   console.log(bar); //foo {a: 2}
   console.log(bar.a); // 2
   

arrow functions

   箭头函数从封闭它的(函数或全局)作用域采用 this 绑定
   function foo() {
     // 返回一个箭头函数
     return (a) => { //箭头函数在词法上捕获 foo() 被调用时的 this(obj1)
       // 这里的 `this` 是词法上从 `foo()` 采用的
       console.log(this.a);
     };
   }
   var obj1 = {
     a: 2
   };
   var obj2 = {
     a: 3
   };
   var bar = foo.call(obj1);
   bar.call(obj2); //2
   
   

Refer:

  https://github.com/CuiFi/You-Dont-Know-JS-CN
  https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/109226.html

相关文章

  • 深入 Parcel--架构与流程篇

    摘要:本篇文章是对的源码解析,代码基本架构与执行流程,带你了解打包工具的内部原理,在这之前你如果对不熟悉可以先到官网了解介绍下面是偷懒从官网抄下来的介绍极速零配置应用打包工具极速打包使用进程去启用多核编译。 showImg(https://segmentfault.com/img/bVbpZRp?w=1241&h=893); 本篇文章是对 Parce 的源码解析,代码基本架构与执行流程,带你...

    yuxue 评论0 收藏0
  • should.js源码分析与学习

    摘要:结构其中为整个项目入口,为中的类,负责对测试信息进行记录。通过抛出错误而不是返回布尔值的方式来通知用户,能够更加明显的通知用户,也方便向上抛出异常进行传递。 背景 为了研究与学习某些测试框架的工作原理,同时也为了完成培训中实现一个简单的测试框架的原因,我对should.js的代码进行了学习与分析,现在与大家来进行交流下。 目录 ext assertion.js assertion-e...

    Turbo 评论0 收藏0
  • 微信小游戏初体验

    摘要:前言前天一个跳一跳小游戏刷遍了朋友圈,也代表了微信小程序拥有了搭载游戏的功能早该往这方面发展了,这才是应该有的形态嘛。作为一个前端,我的大刀早已经饥渴难耐了,赶紧去下一波最新的微信官方开发工具,体验一波小游戏要如何开发。 本文旨在通过分析官方给出的一个飞机大战小游戏的源代码来说明如何进行小游戏的开发。 1.前言 前天一个跳一跳小游戏刷遍了朋友圈,也代表了微信小程序拥有了搭载游戏的功能(...

    elina 评论0 收藏0
  • 一步一步开发安卓下react-native应用系列之进阶篇

    摘要:首先我们打开命令行,切换到项目根目录下,输入安装完成后,请注意,需要把目录下的所有字体文件拷贝到目录下,如果没有该目录,请自行创建。         看过我前面文章的朋友们现在应该能正常运行自己的第一个RN应用了,那都是小儿科,现在我们来做点进阶一点的东西。这篇文章有一些属于干货性的东西,请仔细阅读。特别需要注意我加粗的部分。        首先我们来看下js文件结构,在项目初始化成功...

    xioqua 评论0 收藏0
  • Tooltip组件拆解

    摘要:的组件拆解之的中的组件在目录下。这个组件核心部分是分别涉略了。 Element的组件拆解之Tooltipelement ui的中的 toolpic组件 在 packages/tooltip目录下。 这个组件核心部分是 showImg(https://segmentfault.com/img/bVbnFjF?w=332&h=214); toolpic 分别涉略了。《main.js vue...

    miya 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<