作用域链
- 作用域链:通过创建态决定的
- 手动取消全局作用域:通过块级作用域
let a = 'global'
console.log(a);//'global'
function course() {
let b = 'this指向'
console.log(b);//'this指向'
session()
function session() {
let c = 'this'
console.log(c);//'this'
teacher()
function teacher() {
let d = 'yy'
console.log(d);//'yy'
console.log('test1', b);//'test1' 'this指向'
}
}
}
console.log('test2', b)//b is not defined
course()
函数直接调用: this 指向window
function foo() {
console.log('函数内部的this', this);//window
}
foo()
隐式绑定:this 指向上一级
function fn() {
console.log('隐式绑定', this); // obj
}
const obj = {
a: 1,
}
obj.fn = fn
obj.fn()
面试题:
const foo = {
bar: 10,
fn: function () {
console.log(this.bar);//undefined
console.log(this);//window
}
}
// 取出
let fn1 = foo.fn
// 执行
fn1()
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('01fn', o1.fn());//o1
console.log('02fn', o2.fn());//o1
console.log('03fn', o3.fn());//undefined ( 因为 this 指向 window )
追问:如何改变this指向:现在要将console.log('o2fn',o2.fn())的结果是o2
const o1 = {
text: 'o1',
fn: function () {
return this.text
}
}
const o2 = {
text: 'o2',
fn: o1.fn
}
console.log('01fn', o1.fn());//o1
console.log('02fn', o2.fn());//o2
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('yy')
course.test()
追问:类中同步和异步方法中的this指向有区别吗
class Course {
constructor(name) {
this.name = name
console.log('构造函数内的this', this);//course
}
test() {
console.log('类方法中的this', this);//course
}
asyncTest() {
console.log('异步方法外的this', this);//course
// 普通函数
setTimeout(function () {
console.log('异步方法内的this1', this);//window
}, 100);
// 箭头函数
setTimeout(() => {
console.log('异步方法内的this2', this);//course
}, 200);
}
}
const course = new Course('yy')
course.test()
course.asyncTest()
如何突破作用域的束缚:闭包
- 函数作为返回值:函数外可以访问函数内部的变量
function mail() {
let content = '信'
return function () {
console.log(content);
}
}
const envelop = mail()
envelop()
- 函数作为参数
let content
function envelop(fn) {
content = 1
fn()
}
function mail() {
console.log(content);
}
envelop(mail)
- 函数嵌套:计数器的应用
let count = 0
function outerFn() {
function innerFn() {
count++
console.log(count);
}
return innerFn
}
outerFn()()
- 事件处理(异步)
let lis = document.querySelector('li')
for (let i = 0; i < lis.length; i++) {
(function (i) {
lis[i].onclick = function () {
console.log(i);
}
})(i)
}
- 立即执行嵌套
(function immediateA(a) {
return (function (b) {
console.log(a);//0
})(1)
})(0)
- 当立即执行函数遇到块级作用域
let count = 0;
(function immediate() {
if (count === 0) {
let count = 1
console.log(count); // 1
}
console.log(count); // 0
})()
- 拆分执行
function createIncrement() {
let count = 0
function increment() {
count++
}
let message = `count is ${count}`
function log() {
console.log(message);
}
return [increment, log]
}
const [increment, log] = createIncrement()
increment()
increment()
increment()
log() // count is 0
function createIncrement() {
let count = 0
function increment() {
count++
}
function log() {
let message = `count is ${count}`
console.log(message);
}
return [increment, log]
}
const [increment, log] = createIncrement()
increment()
increment()
increment()
log() // count is 3
- 实现私有变量
function createStack() {
const items = []
return {
push(item){
items.push(item)
}
}
}
//给外界只暴露一个操作变量items的push方法,会形成对变量的保护