作用域链
作用域 从下向上查找 从内向外找
let a = 'try-a'
console.log(a) // try-a
function course() {
let b = 'try-b'
console.log(b) // try-b
session()
function session() {
let c = 'try-c'
console.log(c) // try-c
teacher()
function teacher() {
let d = 'try-d'
console.log(d) // try-d
}
}
}
course()
ES6取消了全局、新增块级作用域
// 块级作用域
if (true) {
let e = 'try'
console.log(e)
}
this 上下文 context
注:this 是在执行时动态读取上下文决定的,不是在定义时决定的
- 在执行函数时,如果函数被上一级所调用,那么上下文即指向上一级
- 否则为全局孤立, 指向window
const o1 = {
text: 'o1',
fn: function () {
return this.text
}
}
const o2 = {
text: 'o2',
fn: function () {
return o1.fn()
}
}
const o3 = {
text: 'o3',
fn: function () {
let fn = o1.fn
return fn()
}
}
console.log(o1.fn()) // o1
console.log(o2.fn()) // o1
console.log(o3.fn()) // undefined
函数直接调用 - this 指向window
function foo () {
let e = 'try'
console.log(this, '函数内部的this')
}
foo()
隐式绑定 - this指向调用堆栈的上一级
function foo () {
console.log(this.a, '隐式绑定的this')
}
const obj = {
a: 1
}
obj.foo = foo
obj.foo()
显示绑定 (bind | apply | call)
function foo () {
console.log(this, '显示绑定的this')
}
foo.call({a: 1})
foo.apply({a: 1})
const bindFoo = foo.bind({a: 1})
bindFoo()
new 生成实例 – this 指向new之后得到的实例
class Course {
constructor (name) {
this.name = name
console.log(this, '构造函数中的this') // Course
}
test () {
console.log(this, '类方法中的this') // Course
}
}
const course = new Course()
course.test()
优先级 — new > 显示函数 > 隐式函数 > 默认
function fn () {
console.log(this)
}
const obj = { fn }
obj.fn() // fn 中的 this 指向 obj
// 显示函数 和 隐式函数 同时存在 显示 > 隐式
obj.fn.bind(111)() // fn 中的 this 111
function foo (a) {
this.a = a
}
// new 和 显示函数 同时存在 new > 显示
const obj1 = {}
var bar = foo.bind(obj1)
bar(2)
console.log(obj1.a) // 2
let baz = new bar(3)
console.log(baz.a) // 3
闭包
一个函数和他周围状态的引用绑定在一起的组合
使用场景:
函数作为返回值
function mail () {
let content = '信'
return function () {
console.log(content)
}
}
const envelop = mail()
envelop()
// 函数外部 获取到了函数作用域内部变量值
函数作为参数
function envelop (fn) {
let content = '1'
fn()
}
function mail () {
let content = 0
console.log(content) // 0
}
envelop(mail)
// 函数作为 参数 获取到了函数作用域内部变量值
函数嵌套
let counter = 0
function outerFn () {
function innerFn () {
counter++
console.log(counter)
}
return innerFn
}
事件处理(异步执行)的闭包
let lis = document.getElementByTagName('li')
for (var i = 0; i < lis.length; i++) {
(function (i) {
lis[i].onclick = function () {
console.log(i) // 不放到闭包内 i 输入的值是 lis 的长度
}
// setTimeout(function () { console.log(i) }, 1000)
})(i)
}
JS实现私有变量
function cresteStack () {
return {
items: [],
push (item) {
this.items.push(item)
}
}
}
const stack = {
items: [],
push: function () {}
}
function cresteStack () {
const items = []
return {
push (item) {
items.push(item)
}
}
}