【闭包与this指向的问题】

一、闭包的概念.

简单的理解就是内层函数可以访问外层函数中的变量
有时候需要用到函数内的局部变量,在正常情况下是不能读取到的,这个时候就需要用到闭包

二、产生闭包的方法有两种方式

在这里插入图片描述
在这里插入图片描述
函数作为参数被传递

// 函数作为参数被传递
function print(fn) {
    const a = 200
    fn()
}
const a = 100
function fn() {
    console.log(a)	// 这个a是自由变量,自由变量的概念就是往上去一层一层去寻找,就找到 a = 100
}
print(fn) // 100

函数作为返回值被返回

// 函数作为返回值
function create() {
    const a = 100
    return function () {
        console.log(a) // 这个跟上面的同理
    }
}
const fn = create()
const a = 200
fn() // 100

函数中的自由变量,取决于函数定义的地方,跟执行的地方没关系

优点:闭包因为长期驻扎在内存中,可以重复使用变量,不会造成变量污染
缺点:闭包会使函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,
否则会造成网页的性能问题,可能会导致内存泄露。解决方法是在退出函数之前,
将不使用的变量全部删除。

三、this指向问题

5大调用场景:

普通函数、
对象方法、
call apply bind
class
箭头函数

普通函数

普通函数this指向window

function fn(){
	console.log(this)
}
fn()	// this指向window
// 其实是 window.fn() 但是window可以省略不写

对象方法

对象方法中的this,指向当前对象

let fox = {
	name:'张三'
	run(){
		console.log(this)
	}
}
fox.run()	// this指向当前调用的对象

call() /apply() /bind() 都可以改变this指向

call apply bind中调用, this指向被传入的对象

//案例一
 let obj={name:'小明'}

  let pox={
    name:'小红',
    run:function(){
      console.log(this.name)
    }
  } 
  // 对象方法中的this.指向方法的调用者。
  pox.run();// pox 小红
  pox.run.call(obj)// 小明
  pox.run.apply(obj);// 小明
  pox.run.bind(obj)();//小明


//案例二
call和apply和bind都可以改变this的指向

// call 可以改变this的指向 将this指向改成第一个参数 
// 第二个参数是单个
// apply 可以改变this的指向 将this指向改成第一个参数
// 第二个参数是一组
function fn(){
	console.log(this)	// this 指向[1,2,3]
}
fn.call([1,2,3])


function foo(){
	// arguments其实就是一个伪数组
	let arg = arguments;
	console.log(arguments);	// [1,2,3]
	// arg.push(4) // 会报错,因为arguments不是真正的数组 是个伪数组
	// 借用array数组的方法 改变this的指向为这个伪数组
	Array.prototype.push.call(arg,4)	// [1,2,3,4]
	// Array.prototype.push.call(arg,[5,6])	// [1,2,3,4,Array(2)]
	let arr = [5,6,7]
	Array.prototype.push.apply(arg,arr)	// [1,2,3,4,5,6,7]
}
foo(1,2,3)


// bind 也可以改变this的指向 需要手动调用
let obj = {name:'李四'}
let fox = {
	name:'张三'
	run(){
		console.log(this)
	}
}
fox.run()
// 第一个括号里面是要改变到哪个this
// 第二个括号是this
fox.run.bind(obj)()	// this指向obj对象

相同点:call() /apply() /bind() 都可以改变this指向,指向第一个参数
不同点:bind()需要手动执行

class(es6新增)

class中的方法中调用, this指向实例对象

class Person(){
	constructor(name,age){
		this.name = name;
		this.age = age;
	}
	say(){
		console.log(`我叫${this.name}年龄是${this.age}`)
	}
}
var person = new Person('哈哈',18)
person.say()	// this指向实例出来的person对象

箭头函数(es6新增)

箭头函数,this指向父级上下文

var name = '李四'
let fox = {
	name:'张三'
	run:(){
		console.log(this.name)
	}
}
fox.run()	// this指向window 所以最后打印出来的是 李四

四、this总结

普通函数中调用,this指向window
对象方法中调用,this指向当前对象
call apply bind中调用, this指向被传入的对象
class中的方法中调用, this指向实例对象
箭头函数,this就是父级上下文
定时器里的this始终指向window

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值