当前位置:网站首页>this+闭包+作用域 面试题
this+闭包+作用域 面试题
2022-07-05 02:41:00 【_语墨】
作用域链
let a = 'global';
console.log(a);
function course() {
let b = 'zhaowa';
console.log(b);
session();
function session() {
let c = 'this';
console.log(c);
teacher();
function teacher() {
let d = 'yy';
console.log(d);
console.log('test1', b);
}
}
}
console.log('test2', b);
course();
报错:b is not defined
if(true) {
let e = 111;
console.log(e);
}
console.log('test3', e)
报错: e is not defined
- 对于作用域链我们直接通过创建态来定位作用域链
- 手动取消全局,使用块级作用域
this - 上下文context
this是在执行时动态读取上下文决定的,而不是创建时
函数直接调用中 this指向的是window(函数表达式、匿名函数、嵌套函数)
function foo(){
console.log(this) //指向window
}
隐式绑定
1.this的指向是调用堆栈的上一级 => 对象、数组等引用关系逻辑
function fn() {
console.log('隐式绑定', this.a);
}
const obj = {
a: 1,
fn
}
obj.fn = fn;
obj.fn();
面试题:
const foo = {
bar: 10,
fn: function() {
console.log(this.bar);
console.log(this);
}
}
let fn1 = foo.fn;
fn1(); //this 指向windows
// 追问1, 如何改变指向
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('o1fn', o1.fn());
console.log('o2fn', o2.fn());
console.log('o3fn', o3.fn());
o1fn o1
o2fn o1
o3fn undefined //指向windows
- 在执行函数时,函数被上一级调用,上下文指向上一级
- or直接变成公共函数,指向window
追问: 现在我要 console.log(‘o2fn’, o2.fn()); 的结果是o2
// 1. 人为干涉,改变this - bind/call/apply
// 2. 不许改变this
const o1 = {
text: 'o1',
fn: function() {
return this.text;
}
}
const o2 = {
text: 'o2',
fn: o1.fn
}
console.log('o2fn', o2.fn());
// this指向最后调用他的对象,把在fn执行时,o1.fn抢过来挂载在自己o2fn上即可
2.new - this指向的是new之后得到的实例
class Course {
constructor(name) {
this.name = name;
console.log('构造函数中的this:', this);
}
test() {
console.log('类方法中的this:', this);
}
}
const course = new Course('this');
course.test();
//指向实例course
追问: 类中异步方法,this有区别吗
class Course {
constructor(name) {
this.name = name;
console.log('构造函数中的this:', this);
}
test() {
console.log('类方法中的this:', this);
}
asyncTest() {
console.log('异步方法外:', this);
setTimeout(function() {
console.log('异步方法内:', this);
}, 100)
}
}
const course = new Course('this');
course.test();
course.asyncTest();

- 执行settimeout时,匿名方法执行时,效果和全局执行效果相同
- 追问 如何解决: 使用箭头函数
显式绑定(bind|apply|call)
function foo() {
console.log('函数内部this', this);
}
foo();
// 使用
foo.call({
a: 1});
foo.apply({
a: 1});
const bindFoo = foo.bind({
a: 1});
bindFoo();
追问:call、apply、bind的区别
- call 、apply 传参不同 依次传入/数组传入
- bind直接返回函数,需要再次执行 传参和call一样
bind 的原理 / 手写bind
原理或手写类题目,解题思路:
1.说明原理,写下注释
2.根据注释,补齐源码
function sum(a, b, c) {
console.log('sum', this);
return a + b + c;
}
// 1. 需求:手写bind => bind位置(挂在那里) => Function.prototype
Function.prototype.newBind = function() {
// 2. bind是什么?
const _this = this;
const args = Array.prototype.slice.call(arguments);
// args特点,第一项是新的this,第二项~最后一项函数传参
const newThis = args.shift();
// a. 返回一个函数
return function() {
// b. 返回原函数执行结果 c. 传参不变
return _this.apply(newThis, args);
}
}
//手写apply
Function.prototype.newApply = function(context) {
// 边缘检测
// 函数检测
if (typeof this !== 'function') {
throw new TypeError('Error');
}
// 参数检测
context = context || window;
// 挂载执行函数
context.fn = this;
// 执行执行函数
let result = arguments[1]
? context.fn(...arguments[1])
: context.fn();
// 销毁临时挂载
delete context.fn;
return result;
}
如何突破作用域的束缚?
闭包
闭包:一个函数和他周围状态的引用捆绑在一起的组合
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 counter = 0;
function outerFn() {
function innerFn() {
counter++;
console.log(counter);
// ...
}
return innerFn;
}
outerFn()();

事件处理(异步执行)的闭包
let lis = document.getElementsByTagName('li');
for(var i = 0; i < lis.length; i++) {
(function(i) {
lis[i].onclick = function() {
console.log(i);
}
})(i);
}
解决:
1.改为立即执行函数,传参形式。
2.将var 改为let
追问:
立即执行嵌套
(function immediateA(a) {
return (function immediateB(b) {
console.log(a); // 0
})(1);
})(0);
立即执行函数遇上块级作用域
let count = 0;
(function immediate() {
if(count === 0) {
let count = 1;
console.log(count);
}
console.log(count);
})();

拆分执行 - 关注
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();
实现私有变量
function createStack() {
return {
items: [],
push(item) {
this.item.push(item);
}
}
}
const stack = {
items: [],
push: function() {
}
}
function createStack() {
const items = [];
return {
push(item) {
items.push(item);
}
}
}
// Vuex store
边栏推荐
- [Yu Yue education] National Open University spring 2019 0505-22t basic nursing reference questions
- Serious bugs with lifted/nullable conversions from int, allowing conversion from decimal
- The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
- Returns the lowest common ancestor of two nodes in a binary tree
- Kotlin - 协程 Coroutine
- CAM Pytorch
- Kotlin - coroutine
- GFS distributed file system
- openresty ngx_ Lua variable operation
- 平台入驻与独立部署优缺点对比
猜你喜欢

Design and implementation of campus epidemic prevention and control system based on SSM

Yolov5 model training and detection

【LeetCode】106. Construct binary tree from middle order and post order traversal sequence (wrong question 2)

2021 Li Hongyi machine learning (2): pytorch

Design of KTV intelligent dimming system based on MCU
![Acwing game 58 [End]](/img/16/c55e0a7aedc354f1c739637ed13a6b.png)
Acwing game 58 [End]

Practical case of SQL optimization: speed up your database
![[source code attached] Intelligent Recommendation System Based on knowledge map -sylvie rabbit](/img/3e/ab14f3a0ddf31c7176629d891e44b4.png)
[source code attached] Intelligent Recommendation System Based on knowledge map -sylvie rabbit

Open source SPL optimized report application coping endlessly

spoon插入更新oracle数据库,插了一部分提示报错Assertion botch: negative time
随机推荐
openresty ngx_lua执行阶段
College Students' innovation project management system
Missile interception -- UPC winter vacation training match
Pgadmin 4 V6.5 release, PostgreSQL open source graphical management tool
RichView TRVStyle MainRVStyle
Icu4c 70 source code download and compilation (win10, vs2022)
Design and practice of kubernetes cluster and application monitoring scheme
Bumblebee: build, deliver, and run ebpf programs smoothly like silk
Moco V2 literature research [self supervised learning]
LeetCode 314. Binary tree vertical order traversal - Binary Tree Series Question 6
2021 Li Hongyi machine learning (3): what if neural network training fails
STL container
Design and implementation of high availability website architecture
Privatization lightweight continuous integration deployment scheme -- 01 environment configuration (Part 1)
Voice chip wt2003h4 B008 single chip to realize the quick design of intelligent doorbell scheme
Introduce reflow & repaint, and how to optimize it?
Design and implementation of campus epidemic prevention and control system based on SSM
【LeetCode】404. Sum of left leaves (2 brushes of wrong questions)
The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
Day_ 17 IO stream file class