JavaScript作用域闭包与this

Posted lime2019

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript作用域闭包与this相关的知识,希望对你有一定的参考价值。

1. JavaScript作用域

作用域代表了变量合法的使用范围。

JavaScript中作用域:

  • 全局作用域;
  • 函数作用域:函数中声明的变量,会成为函数的局部变量,其作用域是局部的;
  • 块级作用域(ES6新增):

自由变量:一个变量如果在当前作用域内没有被定义,但是被使用了。则向上级作用域一层层寻找(链式作用域),直到找到为止,如果到全局作用域还是未找到,报错:xx is not defined

2. JavaScript闭包

闭包就是能够读取其他函数内部变量的函数。从本质上而言,闭包就是将函数内部和外部连接在一起的一座桥梁。

闭包的作用:

  • 读取函数内部的变量;
  • 将函数内部变量的值保持在内存中;

使用闭包注意点:

  • 闭包会使函数中变量存储在内存中,内存消耗大,且在IE中可能造成内存泄漏。(可在退出函数之前将不适用的局部变量删除)
  • 闭包会在父函数外部,修改父函数内部变量的值。
  • 自由变量的查找,在于函数定义的地方,向上级作用域查找,而非在函数执行的地方。

匿名函数、回调函数本身也是一个闭包。

阮一峰《学习Javascript闭包(Closure)》

此知识点主要从两个方面考察(抓住自由变量的作用域即可):

  • 函数作为返回值;
  • 函数作为参数;

3. JavaScript中this

this是 JavaScript 语言的一个关键字。

它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用。

this使用场景:

  • 作为普通函数;
  • 作为对象方法被调用;
  • 作为构造函数被使用;
  • 使用callapplybind
  • 箭头函数;

this取值是函数执行时确定的,而非函数定义时确定的。

this

3.1 作为普通函数执行

let x = 1
function test(){
	console.log(this.x)
}
test() // 1

此时属于全局调用,this代表全局对象。

3.2 作为对象方法执行

function test(){
	console.log(this.x)
}
let obj = { x:1 }
obj.f = test
obj.f() // 1

此时this指向上一级对象

3.3 作为构造函数执行

function test(){
	this.x = 1
}
let obj = new test()
console.log(obj.x) // 1

此时this指向新对象。

3.4 apply等方法中执行

applycallbind方法是Function对象自带的三个方法,作用是改变函数的this指向。

applycallbind方法:

  • 相同点:第一个参数:this要指向的对象,即想要指定的上下文(this关键字的值),其他参数可以传递字符串、数值、布尔值;
  • applycall作用一样,仅接受参数方式不一样,call(this,arg1,arg2,...)apply(this,[arg1,arg2,...])
  • bind返回对应的函数,以便稍后调用,其接受后续参数方式与call相同;

3.5 箭头函数中执行

箭头函数没有自己的this值,其所使用的this来自函数作用域链,即父函数的this值,因此其不能用作构造函数。箭头函数中this指向是固定的

let obj = {
	x : 1,
	test: function(){
		setTimeout(() => {
			console.log(this)
		})
	}
}
obj.test()

代码部分参考博文:
ES6 箭头函数中的 this?你可能想多了(翻译)

4. 拓展

4.1 手写bind函数

Function.prototype._bind = function (){
	// 将参数解析为数组
	const args = Array.prototype.slice.call(arguments)
	// 获取 this (即数组第一项)
	const t = args.shift()
	const self = this
	// 返回函数
	return function(){
		// 执行原函数,并返回结果
		return self.apply(t,args)
	}
} 
Function.prototype._call = function(obj,...args){
	try{
		window
	}catch(error){
		window = null
	}
	obj = obj || window || global
	obj._fun_ = this
	let res = obj._fun_(...args)
	delete obj._fun_
	return res
}

以上是关于JavaScript作用域闭包与this的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript之作用域与闭包详解

作用域与闭包:this,var,(function () {})

JS---闭包

学习Javascript闭包(Closure),涉及到了this指向,变量的作用域

浅谈JavaScript闭包this指针作用域

JavaScript作用域和闭包