当前位置:网站首页>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
边栏推荐
- The database and recharge are gone
- ASP. Net core 6 framework unveiling example demonstration [01]: initial programming experience
- Grub 2.12 will be released this year to continue to improve boot security
- "C zero foundation introduction hundred knowledge and hundred cases" (72) multi wave entrustment -- Mom shouted for dinner
- Pytest (4) - test case execution sequence
- Vb+access hotel service management system
- Visual studio 2019 set transparent background (fool teaching)
- Learn game model 3D characters, come out to find a job?
- Use the difference between "Chmod a + X" and "Chmod 755" [closed] - difference between using "Chmod a + X" and "Chmod 755" [closed]
- 返回二叉树中两个节点的最低公共祖先
猜你喜欢

Yolov5 model training and detection

A label colorful navigation bar

How to make a cool ink screen electronic clock?

The most powerful new household god card of Bank of communications. Apply to earn 2100 yuan. Hurry up if you haven't applied!

Matrixone 0.2.0 is released, and the fastest SQL computing engine is coming
![[200 opencv routines] 99 Modified alpha mean filter](/img/df/1b7beb6746f416198fc405249852f8.jpg)
[200 opencv routines] 99 Modified alpha mean filter

Introduce reflow & repaint, and how to optimize it?

Video display and hiding of imitation tudou.com

Introduce reflow & repaint, and how to optimize it?

Unpool(nn.MaxUnpool2d)
随机推荐
How to make a cool ink screen electronic clock?
Last week's hot review (2.7-2.13)
Icu4c 70 source code download and compilation (win10, vs2022)
Traditional chips and AI chips
Chinese natural language processing, medical, legal and other public data sets, sorting and sharing
openresty ngx_lua变量操作
The most powerful new household god card of Bank of communications. Apply to earn 2100 yuan. Hurry up if you haven't applied!
College Students' innovation project management system
Spark SQL learning bullet 2
LeetCode --- 1071. Great common divisor of strings problem solving Report
Pytest (4) - test case execution sequence
平台入驻与独立部署优缺点对比
Blue bridge - maximum common divisor and minimum common multiple
Moco V2 literature research [self supervised learning]
[机缘参悟-38]:鬼谷子-第五飞箝篇 - 警示之一:有一种杀称为“捧杀”
CAM Pytorch
Grub 2.12 will be released this year to continue to improve boot security
Breaking the information cocoon - my method of actively obtaining information - 3
使用druid连接MySQL数据库报类型错误
ELK日志分析系统