七、this不同场景,如何取值?
this易混场景
1.普通函数下的this
2.call apply bind的this
3.定时器中的this
4.箭头函数中的this
// 1.普通函数中的this
// 非严格模式 this ->window
// 严格模式下 this->undefined
"use strict" //严格模式开关
function a() {
console.log(this);
}
a();
// 2.call apply bind 中的this
// 情况1: this->window
// a.call() window
// a.call(undefined) window
// a.call(null) window
// 情况2:传什么,this就是什么
function a() {
console.log(this);
}
a.call()
a.call(undefined)
a.call(null)
a.apply()
// 都是window
a.apply("abc")
a.call(123)
const fn = a.bind({x:100})
fn()
// 3.定时器中的this
// 情况1:定时器+function this->window
// 情况2:定时器+箭头函数 this->上层作用域的this
// 情况1: 只要计时器里面是这种function,都输出window
// 案例一
// setTimeout(function () {
// console.log(this); //输出 window
// },100)
// 案例二
// function fn() {
// setTimeout(function(){
// console.log(this);
// },100)
// }
// fn.call({x:101}) //输出 window
// 案例三
// const a={
// fn(){
// setTimeout(function () {
// console.log(this); //输出 window
// },100)
// }
// }
// a.fn()
// 情况2:
// 案例一
// class Obj{
// fn(){
// setTimeout(()=>{
// console.log(this); //输出Obj
// },100)
// }
// }
// const o =new Obj()
// o.fn()
//案例二
// function fn() {
// setTimeout(()=>{
// console.log(this); //输出{x:100}
// },100)
// }
// fn.call({x:100})
/*4.箭头函数中的this
情况1:有function作用域的,this是上层作用域的this
情况2:没有function作用域的,this是window*/
// 案例一:obj1是new Obj 是有作用域的
class Obj{
say=()=>{
console.log(this);
}
}
const obj1=new Obj()
obj1.say() //输出Obj
// 案例二:obj2是被定义出来的,没有作用域
const obj2={
say:()=>{
console.log(this);
}
}
obj2.say() //输出window
// 案例三
const oBtn=document.getElementById("btn")
//有作用域
// oBtn.onclick=function(){
// console.log(this); //输出<button id="btn">test</button>
// }
// 没有作用域
// oBtn.onclick=()=>{
// console.log(this);// 输出window
// }
let obj={
x:123,
show(){
setTimeout(()=>{
console.log(this.x);
},100)
}
}
obj.show(); //123
obj.show.call({x:100}) //100
八、手写bind函数
知识点
function.pototype.myBind
Array.prototype.slice.call()
array.shift()
// 原生bind
// function fn(a,b,c){
// console.log(this);
// console.log(a,b,c);
// return "this is return"
// }
// const cb= fn .bind({x:200},1,2,3)
// console.log(cb());
// 手写bind
Function.prototype.myBind = function () {
const fn = this;
// arguments是传进来的所有参数
// 是一个类数组
const arg = Array.prototype.slice.call(arguments);
const _this = arg.shift();
// const _this=arguments[0]
return function () {
return fn.apply(_this, arg);
};
};
const cb = fn.myBind({ x: 2100 }, 1, 2, 3, 4);
function fn(a, b, c,d) {
console.log(this);
console.log(a, b, c,d);
return "this is return";
}
console.log(cb());
九、闭包
什么是闭包
概念:闭包是作用域的一种特殊应用
触发闭包的情况
1.函数当做返回值被返回
2.函数当做参数被传递
3.自执行匿名函数
闭包的应用
1.隐藏变量
2.解决for i 的问题
作用域
全局作用域
局部作用域
自由变量
不在自己作用域里的变量,就是自由变量
自由变量的值:函数定义的地方向上层作用域查找。与调用位置无关
触发闭包的情况
// 情况1:函数当做返回值被返回
function fn() {
const a=1;
return function(){
console.log(a);
}
}
let a=5;
const cb=fn();
cb();
// 情况2:函数当做参数传递
function fn(cb) {
const a=100;
cb();
}
let a=500;
fn(function () {
console.log(a);
});
// 情况3:自执行匿名函数
(function (index){
console.log(index);
})(10);
闭包的应用
<body>
<button>0</button>
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
</body>
<script>
const aBtn = document.getElementsByTagName("button");
for (var i = 0; i < aBtn.length; i++) {
(function (index) {
aBtn[i].onclick = function () {
console.log(index);
};
})(i);
}
//其实一个let就可以解决
// for (let i = 0; i < aBtn.length; i++) {
// aBtn[i].onclick = function () {
// console.log(i);
// };
// }
</script>
隐藏变量
function fn() {
const data={}
return {
set:function(key,val){
data[key]=val;
},get:function(val){
return data[val]
},
}
}
const json=fn();
json.set("age",18);
console.log((json.get("age")));