[译]浅显易懂的 this 取值规则

news/2024/7/7 1:23:35 标签: javascript

翻译自文章The Simple Rules to ‘this’ in Javascript。

确定什么是 this 并非难事。总的来说,通过查找函数被调用时的位置(和方法)就可以决定。遵循以下规则,按优先级排列。

规则

  1. 通过 new 关键字调用构造函数,函数内的 this 是一个全新的对象。

    javascript">function ConstructorExample() {
        console.log(this);
        this.value = 10;
        console.log(this);
    }
    new ConstructorExample();
    // -> {}
    // -> { value: 10 }
  2. 通过 applycallbind 调用一个函数,函数内的 this 就是传入的参数。

    javascript">function fn() {
        console.log(this);
    }
    var obj = {
        value: 5
    };
    var boundFn = fn.bind(obj);
    boundFn();     // -> { value: 5 }
    fn.call(obj);  // -> { value: 5 }
    fn.apply(obj); // -> { value: 5 }
  3. 如果一个函数作为对象的方法调用,即使用 . 符号调用该函数, this 是调用该函数的对象。换句话说,当 . 处于被调用函数的左边,则 this 就是左边的对象。

    javascript">var obj = {
        value: 5,
        printThis: function() {
            console.log(this);
        }
    };
    obj.printThis(); // -> { value: 5, printThis: ƒ }
  4. 如果函数作为普通函数调用,意味着调用方式不符合以上任意一种, this 就是全局对象。在浏览器中就是 window

    javascript">function fn() {
        console.log(this);
    }
    // If called in browser:
    fn(); // -> Window {stop: ƒ, open: ƒ, alert: ƒ, ...}

    *这个规则可以类比于规则3——不同之处在于这个函数自动挂载到了 window 对象上,所以可以这么理解,当我们调用 fn() 时其实调用的事 window.fn() ,所以 this 就是 window

    javascript">console.log(fn === window.fn); // -> true
  5. 如果符合上述多个规则,则越前面的规则会决定 this 的值。
  6. 如果函数是一个 ES2015 箭头函数,会忽略上述所有规则, this 设置为它被创建时的上下文。为了找到 this 的值,需要找到函数被创建时的环境中 this 的值。

    javascript">const obj = {
        value: 'abc',
        createArrowFn: function() {
            return () => console.log(this);
        }
    };
    const arrowFn = obj.createArrowFn();
    arrowFn(); // -> { value: 'abc', createArrowFn: ƒ }

    我们返回去看规则3,当我们调用 obj.createArrowFn() 时, createArrowFn 中的 this 就是 obj 对象,我们用 . 符号调用。如果我们在全局中创建一个箭头函数, this 就是 window

应用规则

下面在几个例子中应用一下我们的规则。试一下通过两种不同的方式调用函数时 this 的值。

找到应用的规则

javascript">var obj = {
    value: 'hi',
    printThis: function() {
        console.log(this);
    }
};
var print = obj.printThis;
obj.printThis(); // -> {value: "hi", printThis: ƒ}
print(); // -> Window {stop: ƒ, open: ƒ, alert: ƒ, ...}

obj.printThis() 很显然应用的是规则3——使用 . 符号。 print() 应用了规则4,在调用 print() 时,我们没有使用 newbind/call/apply. 符号,所以这里的 this 是全局对象 window

多重规则应用

如上文提到,当应用多个规则时,优先应用前面的规则。

javascript">var obj1 = {
    value: 'hi',
    print: function() {
        console.log(this);
    },
};
var obj2 = { value: 17 };

如果规则2和3同时应用,规则2优先。

javascript">obj1.print.call(obj2); // -> { value: 17 }

如果规则1和3同时应用,规则1优先。

javascript">new obj1.print(); // -> {}

关于工具库

一些 JavaScript 库有时候会在函数中主动绑定它认为最有用的内容到 this 上。比如在 JQuery中,在触发事件时 DOM 元素被绑定到了 this 上。在使用工具库时发现取值不符合上述规则时,请查看库文档。很可能使用了 bind 语法。

该文章首发于我的个人站点


http://www.niftyadmin.cn/n/1821617.html

相关文章

Ubuntu16.04 启动纯文本界面方法

问题: Ubuntu16.04 如何启动纯文本界面。 解决方法: 1、系统启动后,在登陆界面点击CtrlShiftF1切换到文本登陆界面; 2、修改为默认从文本界面登陆: sudo vi /etc/default/grub #原内容 GRUB_DEFAULT0 GRUB_HIDDEN_TIM…

seaweedfs

1. 部署 start.cmd start /b weed.exe -log_dir./log/master1/ master -ip127.0.0.1 -port19333 -peers127.0.0.1:19333 -defaultReplication001 -mdir./data/master1/ &start /b weed.exe -log_dir./data/volume1/ volume -ip127.0.0.1 -port28081 -mserver127.0.0.1:1933…

HMAC 挑战/响应双向认证

HMAC结合“挑战/响应”保障数据传输安全 1、流程图: HMAC的一个典型应用是结合“挑战/响应”(Challenge/Response)来保障客户端和服务器传输数据的安全性 。 2、安全性分析: 使用的密钥是双方事先约定的,第三方不可能知…

Python一键安装全部依赖包

requirements.txt用来记录项目所有的依赖包和版本号,只需要一个简单的pip命令就能完成。 pip freeze >requirements.txt然后就可以用 pip install -r requirements.txt 来一次性安装requirements.txt里面所有的依赖包,真是非常方便。 发现了一个全新的…

jekins

devgroup/devgroup转载于:https://www.cnblogs.com/523823-wu/p/8467376.html

Java基础---常见的字符编码有哪些?有什么区别

目录 典型回答 Unicode和UTF-8有啥关系 有了UTF-8,为什么要出现GBK 为什么会出现乱码 典型回答 就像电报只能发出”滴”和”答”声一样,计算机只认识0和1两种字符但是,人类的文字是多种多样的,如何把人类的文字转换成计算机认…

devgridContral

#region 加载gridControl布局项 /// <summary> /// 加载gridControl布局项 /// </summary> private void LoadLayoutFile() { string strLayOutFilePath GdkyConstant.RootDirectory "config\\Layout\\conIn…

HTMLjavaSkcriptCSSjQueryajax(五)

一、Framset标签定义了每个框架中的HTML文档&#xff0c; 1、 <framset cols"25%,75%"> <frame src"frame_a.htm"> <frame src"frame_b.htm"> </frameset> 2、内联框架inframe <iframe src"URL"><…