闭包
-
作为返回值,在程序中返回的函数,由外面的变量引用了,所以不会销毁,从而形成了闭包,help得到的是一个函数,当函数执行的时候,函数会去找执行上下文中的a,即函数app中的a
function app() { let a = 10010; return function () { console.log(a); } } const help = app(); let a = 10086; help();
-
函数作为参数,当函数作为参数传递的时候,传进去的是整个app,app执行的时候会找自己的执行上下文,于是就找到了a = 10086,如果app中没有a变量,那么就会去全局作用域中找,并不会在printf中找
function printf(fn) { let a = 10010 fn() } let a = 10000 function app() { let a = 10086 console.log(a); } printf(app);
this的指向是根据执行上下文来决定的,call,band,apply可以改变this的指向
call() 和 apply() 之间的区别
不同之处是:
call() 方法分别接受参数。
apply() 方法接受数组形式的参数
band() 方法除了返回是函数以外,它 的参数和 call 一样。
详情请参考:https://www.runoob.com/w3cnote/js-call-apply-bind.html
function fn1() {
// 这里的this是指window
console.log(this);
}
// 这里通过call改变了this的指向,指向了{a:100}这个对象
function fn2() {
fn1.call({
a:100});
}
// 这里通过bind改变了this的指向,不过与call不同的是,bind会返回一个新的对象,需要新的变量去接收
let bind = fn1.bind({
a:200})
// 这里可以证明fn1是window对象点出来的,所以指向window没毛病
console.log(window.fn1 === fn1)
fn1()
fn2()
bind()
// 这里使用let关键字声明的对象并不在全局上
let o = {
user:"peter",
fn:function(){
console.log(this.user); //peter
}
}
o.fn();
手写bind方法
Function.prototype.bind1 = function () {
// 将参数解析为数组
const args = Array.prototype.slice.call(arguments);
// 获取this(去除数组第一项,数组剩余的就是传递的参数)
const t = args.shift();
// 谁调用,this就指向谁
const self = this;
// 返回一个函数
return function () {
// 执行原函数,并返回结果
return self.apply(t, args);
}
}
闭包的使用场景(将数据私有化)
function creatCache(){
let data = {
}
return {
set(key, val) {
data[key] = val;
},
get(key) {
return data[key];
}
}
}
let app = creatCache();
app.set('a',100);
console.log(app.get('a'));