一、this的不同应用场景,
如何取值(this取什么样的值,是在函数执行的时候确认,不是定义时确认)
a.作为普通函数
function fn1() {
console.log(this)
}
fn1()
b.使用call apply bind
fn1.call({ x: 100 })
const fn2 = fn1.bind({ x: 200 })
fn2()
c.作为对象方法被调用
const zhangsan = {
name: '张三',
sayHi() {
console.log(this)
},
wait() {
setTimeout(function() {
console.log(this)
})
},
waitAgain() {
setTimeout(() => {
console.log(this)
})
}
}
d.在class方法中调用
class People {
constructor(name) {
this.name = name
this.age = 20
}
sayHi() {
console.log(this)
}
}
const zhangsan = new People('张三')
zhangsan.sayHi()
f.箭头函数
箭头函数没有自己的this,继承外层上下文绑定的this。
1.箭头函数和普通函数区别
1.没有 this,不能改变 this 绑定
2.不能通过 new 调用,当然也没有原型(prototype)
3.不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替
4.箭头函数虽然没有 this ,但是还是可以在内部使用 this 的
5.this 的绑定取决于定义函数时的上下文环境
6.一旦函数调用,任何改变 this 的方法都无效
7.不可以使用`yield`命令,因此箭头函数不能用作 Generator 函数
2.bind和call和apply的区别?
a.相同点
1.bind,call,apply都可以改变this指向
b.不同点
1.call,apply的传参方式不同 apply传数组
2.bind,call,apply的返回值不同 bind返回是函数
c.使用场景:
1.call 判断数据类型,类数据转数组
const array = [1,2,3,4]
const type = Object.prototype.toString.call(array)
console.log(type, 'type 1')
const arrayLike = {
0:'name',
1:'age',
2:'gender',
length: 3
}
const res = Array.prototype.slice.call(arrayLike)
console.log(res, 'res 2')
2.apply 获取数组最大值
const array = [1,2,3,4,5]
const max = Math.max.apply(null, array);
const min = Math.min.apply(null, array);
console.log(max,min, 'max 1')
3.bind react类组件事件响应函数的绑定
3.如何实现new操作符
1.创建空对象
2.获取构造函数
3.对象的__proto__指向Constructor.prototype
4.用apply的方式把构造函数Constructor的this指向obj执行Constructor
5.根据ret的执行结果判断返回构造函数的返回对象还是新创建的空对象
const ObejectFactory = (...args) => {
const obj = {}
const Constructor = [].shift.call(args)
obj.__proto__ = Constructor.prototype
const ret = Constructor.apply(obj, args)
return typeof ret === 'object' ? ret : obj
}
二、手写bind函数
1.将参数解析为数组
2.获取this(取出数组第一项,数组剩余的就是传递的参数)
3.当前函数赋值
4.返回一个函数
5.执行原函数,并返回结果
Function.prototype.bind = function() {
const args = Array.prototype.slice.call(arguments)
const t = args.shift()
const self = this
return function() {
return self.apply(t, args)
}
}
function fn1(a, b, c) {
console.log('this', this)
console.log(a, b, c)
return 'this is fn1'
}
const fn2 = fn1.bind({ x:100 }, 10, 20, 30)
const res = fn2()
console.log(res)
三、作用域
作用域
a.全局作用域
b.函数作用域
c.块级作用域(ES6新增)
if(true) {
let x = 100
}
console.log(x)
自由变量
a.一个变量在当前作用域没有定义,但被使用了
b.向上级作用域,一层一层依次寻找,直至找到为止
c.如果到全局作用域都没有找到,则报错xx is not defined

四、闭包:有权访问另一个函数作用域中的变量的函数
表现:
a.函数作为参数被传递(所有的自由变量的查找,是在函数定义的地方,向上级作用域查找不是在执行的地方)
function print(fn) {
const a = 200
fn()
}
const a = 100
function fn() {
console.log(a)
}
print(fn)
b.函数作为返回值被返回
function create() {
const a = 100
return function() {
console.log(a)
}
}
let fn = create()
const a = 200
fn()
场景
function createCache() {
const data = {}
return {
set: function(key, val){
data[key] = val
},
get: function(key) {
return data[key]
}
}
}
const c = createCache()
c.set('a', 100)
console.log(c.get('a'))
