zoukankan      html  css  js  c++  java
  • 理解js中的函数调用和this

    概述

    这是我看typescript的时候看引用资源看到的,原文在这里:Understanding JavaScript Function Invocation and "this",我简单地总结一下记下来供以后开发时参考,相信对其他人也有用。

    机制

    js中的函数调用机制是这样的:

    1. 建立一个表argList,从索引1开始塞入函数的参数。
    2. 表的索引0的值是thisValue。
    3. 把this赋给thisValue,然后调用func.call(argList)。

    说这么多,其实就是想说明,函数调用f(x,y)其实就是f.call(this, x, y)的语法糖。内部是通过f.call(this, x, y)来调用的。

    可以看到,虽然f(x,y)里面没有this,但是f.call(this, x, y)里面有this,所以非常好理解为什么函数调用中会有this了。

    那么this是从哪里来的呢?当f(x,y)没有调用者的时候,this自动被赋值为window;当f(x,y)有调用者的时候,this被赋值为指向调用者。

    例子

    举几个实例感受一下:

    //例子1
    function hello(thing) {
      console.log(this + " says hello " + thing);
    }
    hello.call("Yehuda", "world"); //输出Yehuda says hello world
    
    //例子2
    function hello(thing) {
      console.log(this + " says hello " + thing);
    }
    //相当于hello.call(window, "world");
    hello("world"); // 输出[object Window] says hello world
    
    //例子3
    function hello(thing) {
      console.log(this + " says hello " + thing);
    }
    let person = { name: "Brendan Eich" };
    person.hello = hello;
    //相当于hello.call(person, "world");
    person.hello("world"); //输出[object Object] says hello world
    

    注意:我们这里不是strict mode。

    更优雅的写法

    有时候,我们希望函数没有调用者,但是this却不指向window对象。有以下2种优雅的解决方案:

    箭头函数

    es6里面定义了箭头函数,不只是为了简化函数的写法,而且还有这么一条有用的规定:箭头函数的this不会随调用者的不同而变化,它的this永远是被定义的函数域中的this。

    //不用箭头函数
    let person = {
        hello: function(thing) {
            return function() {
                console.log(this + " says hello " + thing);
            }
        }
    }
    let helloTest = person.hello('world');
    helloTest(); //输出[object Window] says hello world
    
    
    //使用箭头函数
    let person = {
        hello: function(thing) {
            return () => {
                console.log(this + " says hello " + thing);
            }
        }
    }
    let helloTest = person.hello('world');
    helloTest(); //输出[object Object] says hello world
    

    需要注意的是,需要用一个function()把箭头函数包裹起来,因为如果不这样的话,它被定义的函数域是window。

    bind

    用箭头函数有点麻烦,我们可以这么写一个bind函数达到效果。

    let person = {
        hello: function(thing) {
            console.log(this + " says hello " + thing);
        }
    }
    
    let bind = function(func, thisValue) {
        return function() {
            return func.apply(thisValue, arguments)
        }
    }
    
    let boundHello = bind(person.hello, person);
    boundHello('world'); //输出[object Object] says hello world
    

    es5给所有Function封装了上面的bind方法,所以我们只需要这么写:

    let person = {
        hello: function(thing) {
            console.log(this + " says hello " + thing);
        }
    }
    
    let boundHello = person.hello.bind(person);
    boundHello('world'); //输出[object Object] says hello world
    

    这就是bing()方法的来历0.0

  • 相关阅读:
    Mac OS X系统下编译运行C代码
    Android intent传递list或对象
    Android中实现自定义的拍照应用
    由闭包引起的对javascript代码可维护性的思考
    让浏览器非阻塞加载javascript的几种方式
    Javascript中正则表达式的全局匹配模式
    解读JavaScript代码 var ie = !-[1,]
    Javascript中闭包的作用域链
    WPF代码注意事项,开发常见问题,知识总结
    WPF绑定各种数据源之object数据源
  • 原文地址:https://www.cnblogs.com/yangzhou33/p/8655100.html
Copyright © 2011-2022 走看看