概述

这是我看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

理解js中的函数调用和this的更多相关文章

  1. 图文结合深入理解 JS 中的 this 值

    图文结合深入理解 JS 中的 this 值 在 JS 中最常见的莫过于函数了,在函数(方法)中 this 的出现频率特别高,那么 this 到底是什么呢,今天就和大家一起学习总结一下 JS 中的 th ...

  2. 深入理解JS中的对象(三):class 的工作原理

    目录 序言 class 是一个特殊的函数 class 的工作原理 class 继承的原型链关系 参考 1.序言 ECMAScript 2015(ES6) 中引入的 JavaScript 类实质上是 J ...

  3. 深入理解Js中的this

    深入理解Js中的this JavaScript作用域为静态作用域static scope,但是在Js中的this却是一个例外,this的指向问题就类似于动态作用域,其并不关心函数和作用域是如何声明以及 ...

  4. 怎么理解js中的事件委托

    怎么理解js中的事件委托 时间 2015-01-15 00:59:59  SegmentFault 原文  http://segmentfault.com/blog/sunchengli/119000 ...

  5. 如何更好的理解js中的this,分享2段有意思的代码

    关于js中this的浅析,大家可以点击[彻底理解js中this的指向,不必硬背]这篇博客了解. 今天遇到2段比较有意思的代码. ----------------第一段----------------- ...

  6. 深度理解js中var let const 区别

    首先要理解js中作用域的概念 作用域:指的是一个变量的作用范围 1.全局作用域 直接写在script中的js代码,在js中,万物皆对象,都在全局作用域,全局作用域在页面打开时创建,在全局作用域中有一个 ...

  7. 如何理解js中的this和实际应用中需要避开哪些坑

    this是什么 this就是函数内部的关键字 看下面例子理解js中的this // 例子1 function fnOne () { console.log(this) } 'use strict' f ...

  8. 深入理解JS中的对象(二):new 的工作原理

    目录 序言 不同返回值的构造函数 深入 new 调用函数原理 总结 参考 1.序言 在 深入理解JS中的对象(一):原型.原型链和构造函数 中,我们分析了JS中是否一切皆对象以及对象的原型.原型链和构 ...

  9. 理解js中私有变量

    私有变量在js中是个什么概念.当下我的认识是var所定义的变量,实际可以理解为属性和方法,或者单单是临时存储器,不归属任何对象. 一个声明函数: function a(){  var v = &quo ...

随机推荐

  1. 一个linux bbr存在的调用顺序bug

    最近跟踪bbr的状态转换的代码,发现一个问题: [,min_rtt_us=,full_bw=,cycle_idx=,pacing_gain=,cwnd_gain=,rtt_cnt= [,min_rtt ...

  2. html----input标签

    HTML 5 <input> 标签 定义和用法 <input> 标签规定用户可输入数据的输入字段. 根据不同的 type 属性,输入字段有多种形态.输入字段可以是文本字段.复选 ...

  3. python入门(四):字符串、编码、random

    1.字符串 字符串基本有两种类型,str和bytes >>> s="a" >>> type(s) <class 'str'>     ...

  4. JAVA中的配置文件XML

    一:概念 1.XML  Extensible markup Language 可拓展标记语言 2.功能:存储数据(配置文件,在网络中传输数据) 3.html和xml的区别 3.1xml标记全是自定义的 ...

  5. Java学习笔记(十八):static关键字

  6. CSS文本超出指定行数省略显示

    单行: overflow: hidden; text-overflow: ellipsis; white-space: nowrap; 2行: font-size: 17px;overflow: hi ...

  7. [剑指Offer]38-字符串的全排列

    链接 https://www.nowcoder.com/practice/fe6b651b66ae47d7acce78ffdd9a96c7?tpId=13&tqId=11180&tPa ...

  8. Python开发——变量

    变量的作用 把程序运行的中间结果,临时保存到内存里,以备后面的代码继续调用 变量的声明 name = “yuan” 变量的定义规则 1.变量名只能是  字母.数字或下划线的任意组合 2.变量名的第一个 ...

  9. 手机服务器微架构设计与实现 之 http server

    手机服务器微架构设计与实现 之 http server ·应用 ·传输协议和应用层协议概念 TCP  UDP  TCP和UDP选择 三次握手(客户端与服务器端建立连接)/四次挥手(断开连接)过程图 · ...

  10. 判断是否是json

    转:https://blog.csdn.net/dy_smile/article/details/46739251 function isJson(obj) { var isjson = typeof ...