javascript你必须要知道的——作用域和闭包
JavaScript 知道 必须 作用域 闭包
2023-06-13 09:17:15 时间
介绍
本期介绍作用域和闭包的知识点和题目。包括作用域,自由变量,闭包,this 等部分。作用域是 “JS 三座大山” 之二,不知道闭包的话,面试通过概率不大。
主要内容
- 什么是作用域?什么是自由变量?
- 什么是闭包?闭包会用在哪里?
- this 有几种赋值情况 关键字
- 作用域
- 闭包
- this
什么是作用域?
变量合法的使用范围
- 全局作用域:在全局都可以使用
- 函数作用域:只能在当前函数内使用
- 块级作用域(ES6新增):if,for,while语法里
// ES6 块级作用域
if (true) {
let x = 100
}
console.log(x) // 会报错
什么是自由变量?
- 一个变量在当前作用域没有定义,但被使用了
- 向上级作用域一层一层依次寻找,直到找到为止
- 如果到全局作用域都没找到,则报错 xx is not defind 什么是闭包? 作用域应用的特殊情况,指有权访问另一个函数作用域中的变量的函数
有两种情况:
- 函数作为参数被传递
- 函数作为返回值被返回
// 函数作为返回值
function create() {
let a = 100
return function () {
console.log(a)
}
}
let fn = create()
let a = 200
fn()
// 函数作为参数
function print(fn) {
let a = 200
fn()
}
let a = 100
function fn() {
console.log(a)
}
print(fn)
注意:所有自由变量的查找是在函数定义的地方,向上级作用域查找,不是在执行的地方
闭包会用在哪里?
- 场景一:采用函数引用方式的setTimeout调用
- 场景二:回调
- 场景三:函数防抖
- 场景四:封装私有变量
实际开发中闭包多用于隐藏数据 ,只提供API进行修改数据
this 有几种赋值情况
- 作为普通函数被调用,指向的是window
- 使用call、apply、bind 可以改变this的指向
apply和call会让当前函数立即执行,而bind会返回一个函数,后续需要的时候再调用执行
- 作为对象的方法被调用,指向当前对象
- 在class方法中调用,指向当前创建的实例constructor
- 箭头函数中的this永远是取他上级作用域的this
注意:this取什么值是在函数执行的时候确定的,不是在函数定义的时候确定的
手写call、apply、bind
手写call
function myCall() {
const content = [].shift.call(arguments) || window;
content.fn = this;
const result = content.fn(...arguments);
delete content.fn;
return result;
}
Function.prototype.myCall = myCall;
fn.myCall(obj, 'arg1', 'arg2'); // {a: '这是obj'}
手写apply
function myApply() {
const content = [].shift.call(arguments) || window;
content.fn = this;
const result = content.fn(...arguments[0]);
delete content.fn;
return result;
}
Function.prototype.myApply = myApply;
fn.myApply(obj, ['arg1', 'arg2']); // {a: '这是obj'}
手写bind
function myBind() {
const content = [].shift.call(arguments) || window;
content.fn = this;
const args = arguments;
return () => {
const result = content.fn(...args);
delete content.fn;
return result;
}
}
Function.prototype.myBind = myBind;
fn.myBind(obj, 'arg1', 'arg2')(); // {a: '这是obj'}
示例:
const obj = {a: '这是obj'};
function fn(arg1, arg2) {
console.log(this);
}
fn.call(obj, 'arg1', 'arg2'); // {a: '这是obj'}
fn.apply(obj, ['arg1', 'arg2']); // {a: '这是obj'}
fn.bind(obj, 'arg1', 'arg2')(); // {a: '这是obj'}
原理:
- 3个方法第一个参数为新的执行环境,所以是一个对象
- 将当前执行环境赋值给新环境的某个属性
- 使用新环境调用当前执行环境,相当于一个对象调用方法,方法的this就是这个对象
- 新环境是一个对象所以为引用类型,新增一个属性会改变自身,所以调用之后获得结果需要删除新增的属性 补充 - 原型中的 this
注:此原型图解可对照[JS基础—原型和原型链](https://blog.csdn.net/qq_37215621/article/details/126790301)中class 实现继承定义的类理解
解释:直接xiaoluo.sayhai,调用对象是xiaoluo,所以this是能找到的用__proto__原型去访问的话,调用对象是__proto__,所以name和number是未定义的
相关文章
- javascript 幻灯片代码(含自动播放)「建议收藏」
- javascript_JavaScript走向成熟
- 你不知道的javascript中类型和valueOf()和toString()~~!!
- 你不知道的JavaScript APIs
- 面试题之:JavaScript中this以及apply/call/bind的用法
- javascript-你可能不知道的数组
- 分享 8 个常用的 JavaScript 库,也许你用的上
- 你也许不知道的 JavaScript 高级函数
- javascript实现划词标记划词搜索功能修正版
- Javascript更新JavaScript数组的uniq方法
- 在C#中调用VBScript、javascript等脚本的实现代码
- javascript函数参数原来是可以有缺省值的
- 你需要知道的10个最佳javascript开发实践小结
- Javascript异步加载详解(浏览器在javascript的加载方式)
- JavaScript高级程序设计(第3版)学习笔记8js函数(中)
- javascript判断是否有对RadioButtonList选项选择
- 你必须知道的JavaScript中字符串连接的性能的一些问题
- 利用noesis.Javascript开源组件.Net中执行javascript脚本
- Eclipse去除js(JavaScript)验证错误
- JavaScript程序员应该知道的45个实用技巧
- javascript文件中引用依赖的js文件的方法
- Javascript基础教程之JavaScript语法
- 在JavaScript中重写jQuery对象的方法实例教程