概述

这是我看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. java.util.HashSet, java.util.LinkedHashMap, java.util.IdentityHashMap 源码阅读 (JDK 1.8.0_111)

    一.java.util.HashSet 1.1 HashSet集成结构 1.2 java.util.HashSet属性 private transient HashMap<E,Object> ...

  2. Python实现EXCEL表格的排序功能

    EXCEL的数值排序功能还是挺强大的,升序.降序,尤其自定义排序,能够对多个字段进行排序工作. 那么,在Python大法中,有没有这样强大的排序功能呢?答案是有的,而且本人觉得Python的排序功能, ...

  3. mysql 按出现次数排序

    SELECT * FROM table a LEFT  JOIN (SELECT key,count(*) as c FROM table GROUP BY key )  b on a.key=b.k ...

  4. Jenkins安装时Web页面报错提示离线安装

    先跳过所有. 方法1 先看它的提示:”参考离线Jenkins安装文档“发现链接点不开,我还以为是被墙了呢,FQ以后还是打不开.看来这个参考文档是没有用滴.点击配置HTTP代理跳出如下界面:安装Jenk ...

  5. 引用计数——深拷贝&浅拷贝

    下面是用代码实现: private: char *data; size_t use_count; public: //构造函数 String_rep() { if(str == NULL) { dat ...

  6. AltiumDesigner印制导线的走向及形状

    印制导线的走向及形状.在PCB布线时,相邻层的走线方向成正交结构,应避免将不同的信号线在相邻走成同一方向,以减少不必要的层间窜扰.当PCB布线受到结构限制(如某种背板)难以避免出现平行布线时,特别是当 ...

  7. spring整合mybatis在使用.properties文件时候遇到的问题

    在spring里使用org.mybatis.spring.mapper.MapperScannerConfigurer 进行自动扫描的时候,设置了sqlSessionFactory 的话,可能会导致P ...

  8. python深入理解类和对象

    1,鸭子类型和多态 当看到一只鸟走起来像鸭子,游泳起来像鸭子,叫起来也像鸭子,那这只鸟就是鸭子 是不是比较混乱,看个例子: # -*- coding:UTF-8 -*- __autor__ = 'zh ...

  9. [leetcode]54. Spiral Matrix螺旋矩阵

    Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral or ...

  10. js、jquery、jsp的区别

    1.JSP全称是java server page    JS全称是javaScript 2.最主要的区别是运行位置不同. JSP运行在后台服务器上,混合在HTML中的java程序段用于控制HTML的动 ...