this的五种指法

this 到底指向哪里

以下如果没提及,则为严格模式。

js中作用域有两种:

  1. 词法作用域
  2. 动态作用域

词法作用域

词法作用域指在书写代码时就被确定的作用域。
看如下代码


    var value = 1;

    function foo() {
        console.log(value);
    }

    function bar() {
        var value = 2;
        foo();
    }

    bar();// 结果是1

动态作用域

动态作用域指在代码运行时才被确定的作用域。
js中只有this的作用域是动态作用域

this的五种绑定

初学js时,会想当然认为this遵循某一条规律,就像物理学那样,然而并不是。
this的绑定分为五种情况,这五种情况之间毫无规律可言。不过好在都很简单。

一. 默认绑定

当以如下形式执行一个函数时,this为默认绑定;


    func()
  • 严格模式下,this为undefined
  • 非严格模式下,this是全局对象。

与函数调用嵌套多少层如何嵌套无关


/* 全是undefined */
function printThis(){
    return this
}
var obj = {
    say(){
        console.log(‘obj.say‘,printThis())
    }
}
function funcB(){
    console.log(‘funcB‘,printThis());
    obj.say();
}
console.log(‘funcA‘,printThis())
obj.say()
funcB()

二. 隐式绑定

当以如下行驶执行一个函数时,this为隐式绑定;


a.b.func()

此时this指向前面一个对象

赋值会改变隐式绑定this的指向

  • 方法赋值给变量

class T {
    dotInvoke() {
        console.log(‘dotInvoke‘, this.sayThis())
    }
    sayThis() {
        return this
    }
    assignInvoke() {
        var sayThis = this.sayThis;
        console.log(‘assignInvoke‘, sayThis())
    }
}
var tt = new T();
tt.dotInvoke()// 指向T
tt.assignInvoke()// undefined
  • 函数被赋值成方法

function printThis(){
    return this
}
var obj = {};
obj.say = printThis;
obj.say()/* 指向obj */
  • 赋值给参数

极为常见的是回调函数的this是undefined,因为回调函数被复制给参数,参数再调用时变成了默认绑定


function asyncFun(cb){
    cb()
}
var obj = {
    callback(){
        console.log(this)
    }
}
obj.callback()/*隐式绑定 obj */
asyncFun(obj.callback);/*默认绑定 undefined */

三. 箭头函数

箭头函数会让this指向最近的函数或全局作用域

  • 与最近的函数的this指向相同

    function foo() {
        // 返回一个箭头函数
        return (a)=>{
            //this 继承自 foo()
            return this.a
        }
        ;
    }
    var obj1 = {
        a: ‘obj1‘
    };
    var obj2 = {
        a: ‘obj2‘
    }
    var arrow1 = foo.call(obj1);
    var arrow2 = foo.call(obj2);
    var arrow3 = foo();
    console.log(‘arrow1‘,arrow1())/* obj1 */
    console.log(‘arrow2‘,arrow2())/* obj2 */
    console.log(‘arrow3‘,arrow3())/* undefined,严格模式下报错 */
  • 指向全局

var printThis = ()=>this;
console.log(‘printThis‘,printThis());/* global */
  • 指向实例

class Test {
    printThis = ()=>{
        return this
    }
}
//会被babel翻译成
var test = function test() {
  var _this = this;

  this.printThis = function () {
    return _this;
  };
};

四. 显示绑定

call, apply, bind指定this指向

五. new绑定

构造函数,ES6中的class
new构造函数,new class时,this指向实例

总结

  1. 五种绑定,后面两种情况单一,前面两种会因为方法,函数被赋值而互相转化。
  2. 因为this处于动态作用域,而目前开发时又大量使用框架。我们写下的代码,并不总是由我们自己调用,而是被打包工具打包后,由框架调用。导致我们并不知道我们写下的函数和方法是否被框架复制过或显示绑定过而改变了this指向。以至this指向更加扑朔迷离。
  3. 写完本文顿时觉得,python里指向明确的self完爆js的this。

来源:https://segmentfault.com/a/1190000017715350

原文地址:https://www.cnblogs.com/lovellll/p/10225272.html

时间: 2024-10-02 11:02:57

this的五种指法的相关文章

Meteor 中的代码包有点特殊,分为五种

Meteor 中的代码包有点特殊,分为五种: Meteor 核心代码本身分成多个核心代码包(core package),每个 Meteor 应用中都包含,你基本上不需要花费精力来维护它们 常规 Meteor 代码包称为"isopack",或同构代码包(isomorphic package,意味着它们既能在客户端也能在服务器端工作).第一类代码包例如 accounts-ui 或 appcache 由 Meteor 核心团队维护,与 Meteor 捆绑在一起. 第三方代码包就是其他用户开发

五种方式让你在java中读取properties文件内容不再是难题

一.背景 最近,在项目开发的过程中,遇到需要在properties文件中定义一些自定义的变量,以供java程序动态的读取,修改变量,不再需要修改代码的问题.就借此机会把Spring+SpringMVC+Mybatis整合开发的项目中通过java程序读取properties文件内容的方式进行了梳理和分析,先和大家共享. 二.项目环境介绍 Spring 4.2.6.RELEASE SpringMvc 4.2.6.RELEASE Mybatis 3.2.8 Maven 3.3.9 Jdk 1.7 Id

Unix网络编程中的五种I/O模型_转

转自:Unix网络编程中的的五种I/O模型 下面主要是把unp第六章介绍的五种I/O模型. 1. 阻塞I/O模型 例如UDP函数recvfrom的内核到应用层.应用层到内核的调用过程是这样的:首先把描述符.接受数据缓冲地址.大小传递给内核,但是如果此时 该与该套接口相应的缓冲区没有数据,这个时候就recvfrom就会卡(阻塞)在这里,知道数据到来的时候,再把数据拷贝到应用层,也就是传进来的地址空 间,如果没有数据到来,就会使该函数阻塞在那里,这就叫做阻塞I/O模型,如下图: 2. 非阻塞I/O模

java线程五种状态

java线程五种状态: 创建 -> 就绪 -> 运行 -> 销毁 创建 -> 就绪 -> 运行 -> 等待(缺少资源) -> 销毁 下图:各种状态转换

js五种设计模式说明与示例

第一种模式:js工厂模式 var lev=function(){         return "啊打";      };      function Parent(){             var  Child = new Object();             Child.name="李小龙";             Child.age="30";             Child.lev=lev;           retur

五种常见的 PHP 设计模式

内容 设计模式 一书将设计模式引入软件社区,该书的作者是 Erich Gamma.Richard Helm.Ralph Johnson 和 John Vlissides Design(俗称 "四人帮").所介绍的设计模式背后的核心概念非常简单.经过多年的软件开发实践,Gamma 等人发现了某些具有固定设计的模式,就像建筑师设计房子和建筑物一样,可以为浴室的位置或厨房的构造方式开发模板.使用这些模板或者说设计模式 意味着可以更快地设计更好的建筑物.同样的概念也适用于软件. 设计模式不仅代

Linux下的五种IO模型

5种IO模型 Linux下五种IO模型 (1)阻塞I/O:什么都不干,导致应用程序阻塞,等待数据准备好,如果数据没有准备好,一直阻塞,等数据准备好了从内核拷贝到用户空间 (2)非阻塞I/O:把一个套接字接口设置为非阻塞,告诉内核,当所请求的IO无法完成时,不要将进程睡眠,而是返回一个错误,这样IO操作函数会不断地测试数据是否准备好,如果没有准备好 ,继续测试,直到准备好为止 (3)I/O复用(select epoll):select或epoll会使进程阻塞,但是和阻塞IO不同的是,这两个函数可以

android五种数据存储方式

在Android中提供了如下五种数据存储方式: SharedPreferences 文件存储 SQLite数据库方式 内容提供器(ContentProvider) 网络存储 下面具体介绍一下这五种数据存储方式的用法. 1. SharedPreferences SharedPreferences是android平台上的一个轻量级存储类,主要保存一些常用的配置信息.可以保存long.int.String类型数据. SharedPreferences以键值对方式读取和存入,最终会以XML方式保存数据,

android五种布局模式

Android布局是应用界面开发的重要一环,在Android中,共有五种布局方式,分别是:LinearLayout (线性布局),FrameLayout(框架布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局). 一. 线性布局 线性布局.每一个LinearLayout里面又可分为垂直布局(android:orientation="vertical")和水平布局(android:orientation="