fortran中call的用法_一次搞定 JavaScript 中的 this

7a696e60937564607fe4bf0f339c7369.png
本文首发于我的 GitHub 博客

小白前端学习 JavaScript 过程中遇到的第一道坎,大概率就是 this 了。曾经我也被 this 搞的非常头大,还看过不少博客,但我觉得大多数文章写的有些复杂或者又引入了一些新的概念,加大了理解难度。本文就站在各位前辈大佬的肩膀上,做一下总结升华,目的就是让大家一次搞定 JavaScript 中的 this。

本文会引入的概念

  1. 函数调用,知道 fnfn() 不一样就行,fn() 是函数调用
  2. 隐式调用,不含有 callapplybind 的函数调用就是隐式调用,反之就是显示调用
  3. 箭头函数,知道长的像 fn = () => {} 这样的函数叫箭头函数就行
  4. call的用法,知道 call() 的第一个参数可以指定 fn 的 this 就行,bindapply 同理
  5. 形参、实参,知道函数定义时的参数叫形参,调用时传入的参数叫实参就行

三步确定 this

1. 一“定”——函数调用this定

函数调用的时候确定 this 指向,可以把 this 看成一个隐藏参数。

var a = 10;
function fn() {
	var a = 1;
  	console.log(this.a);
}

fn() // 调用的时候才确定this,默认是undefined,浏览器把它改成了window,var声明的变量会自动挂到window下,所以输出10

2. 二“转”——箭头转外,隐式转call

箭头函数调用

看这个函数的类型,如果是箭头函数,看它外面的 this。

var fn = () => {
  console.log(this.id);
}
var id = 21;
foo(); // 21,因为外面的this是undefined,非严格模式下浏览器会自动转成window,var声明的变量被自动挂到window,所以输出21

普通函数隐式调用

  1. fn(1, 2) 转化成 fn.call(undefined, 1, 2)
  2. obj.fn('hello') 转化成 obj.fn.call(obj, 'hello')
  3. arr[0]() 转化成 arr.0.call(arr, 'x')

来一道综合题一次性说完:

var id = 10
var obj = {
  id: 1,
  foo: function(){
    console.log(this.id)
  }
}
function fn (){ console.log(this) }
var arr = [fn, fn2]

var bar = obj.foo
obj.foo() // 1
bar() // 10
arr[0]() // arr

3. 三“特例”——三种特例别踩坑

new 会改变 this

function Person (name) {
  this.name = name
}
var name = 'window'
var person1 = new Person('Varian')
console.log(person1.name) // Varian

严格模式保持 undefined

严格模式下值为 undefined 的 this 不会变成 window

"use strict"; // 开启严格模式
var a = 10;
function foo () {
  console.log('this1', this) // 'this1' undefined
  console.log(window.a) // 10
  console.log(this.a) // Uncaught TypeError: Cannot read property 'a' of undefined
}
console.log(window.foo) // f foo() {...}
console.log('this2', this) // 'this2' Window{...}
foo();

let const 不会被挂到 window

let x = 10
const y = 20

function foo () {
  console.log(this.x) // undefined
  console.log(this.y) // undefined
}

foo();
console.log(window.x) // undefined

看完有没有感觉 this 其实也并不难呢?来几道综合题巩固一下吧!

综合题

  1. 结合 DOM
button.onClick = function(e) {
  console.log(this);
}

答案不是 button,而是不确定,因为都没有调用,怎么知道 this 呢?

可以这么回答:因为没有调用,所以无法确定 this,如果采用隐式调用的话,打印 button,如果使用显示调用,则打印自定义的 this。

2. 一道超难面试题

let length = 10;
function fn() {
  console.log(this.length);
}

let obj = {
  length: 5,
  method(fn){
  	fn()
    arguments[0]()
	}
}

obj.method(fn, 1);

这道题我们仔细分析一下就会发现有几大坑:let、window.length、arguments.length

所以答案也非常诡异:

不确定(window.length = 页面的iframe数量)
2(arguments.length = 实参长度,非形参)

关于 window.length 的值如何确定,可以参见 MDN。

总结

记住一“定”,二“转”,三特例就行,核心是两点:

  1. 调用时确定 this
  2. 隐式调用上公式 obj.fn(1) = obj.fn.call(obj, 1)

这样一来 this 就真相大白了!


参考文章

  1. 《this 的值到底是什么?一次说清楚》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值