文章目录
- 1. ES6 常用的一些特性
- 2. JS 类型检测的方法
- 2.1 typeof 操作符:
- 2.2 instanceof 操作符:
- 2.3 Object.prototype.toString() 方法:
- 2.4 Array.isArray() 函数:
- 3. 本地存储方式
- cookie
- Web Storage(localStorage 和 sessionStorage)
- indexedDB
- 4.JS 模块化方案
- CommonJS 和 ES6 Module 的使用和区别
- 5.Webpack 常使用的 Loader 和 Plugin
- 6.HTTP 缓存
- 7.call、apply、bind
- call 方法:
- apply 方法:
- bind 方法:
- 7.函数柯里化
- 8.什么是 js 的闭包?有什么作用?
1. ES6 常用的一些特性
- 块级作用域(Block Scope): 使用 let 和 const 关键字声明的变量具有块级作用域,不再受限于函数作用域。
- 箭头函数(Arrow Function): 使用箭头 (=>) 定义函数,简化了函数的书写,更加简洁明了,并且自动绑定了上下文。
- 解构赋值(Destructuring Assignment): 可以通过解构赋值语法从数组或对象中提取值并赋给变量,使得代码更简洁。
- 默认参数(Default Parameters): 函数的参数可以设置默认值,当调用函数时没有传递对应参数时,将使用默认值。
- 模板字符串(Template Strings): 使用反引号 (`) 包裹的字符串,可以插入变量和表达式,并支持多行字符串。
- 类与模块(Classes and Modules): 引入了 class 关键字来定义类,支持面向对象的编程方式。模块化开发得到了原生的支持,使用 import 和 export 来导入和导出模块。
- 箭头函数(Arrow Function): 使用箭头 (=>) 定义函数,简化了函数的书写,更加简洁明了,并且自动绑定了上下文。
- Promise 和异步编程(Promises and Asynchronous Programming): 引入了 Promise 对象,提供了更优雅的处理异步操作的方式,避免了回调地狱的问题。
- 迭代器和生成器(Iterators and Generators): 可以通过迭代器对象遍历数据集合,并且生成器函数可以用于创建迭代器对象,使得迭代操作更加灵活。
- 模块化开发(Module Development): ES6 提供了原生的模块化支持,通过 import 和 export 可以轻松导入和导出模块,实现代码的模块化组织和复用。
2. JS 类型检测的方法
2.1 typeof 操作符:
- typeof 操作符可以用来检测一个值的类型。它返回一个表示值类型的字符串。例如:
typeof "Hello" // 返回 "string"
typeof 42 // 返回 "number"
typeof true // 返回 "boolean"
typeof undefined // 返回 "undefined"
typeof null // 返回 "object"(这是一个历史遗留问题)
typeof {} // 返回 "object"
typeof [] // 返回 "object"
typeof function() {} // 返回 "function"
2.2 instanceof 操作符:
- instanceof 操作符可以用来检测一个对象是否是某个构造函数的实例。例如:
const obj = {};
obj instanceof Object; // 返回 trueconst arr = [];
arr instanceof Array; // 返回 truefunction Person() {}
const person = new Person();
person instanceof Person; // 返回 true
2.3 Object.prototype.toString() 方法:
- 这是一个通用的方法,可以返回一个对象的具体类型。通过将对象作为 this 调用 toString() 方法,并提取返回值中的类型信息。例如:
Object.prototype.toString.call("Hello"); // 返回 "[object String]"
Object.prototype.toString.call(42); // 返回 "[object Number]"
Object.prototype.toString.call(true); // 返回 "[object Boolean]"
Object.prototype.toString.call(undefined); // 返回 "[object Undefined]"
Object.prototype.toString.call(null); // 返回 "[object Null]"
Object.prototype.toString.call({}); // 返回 "[object Object]"
Object.prototype.toString.call([]); // 返回 "[object Array]"
Object.prototype.toString.call(function() {}); // 返回 "[object Function]"
2.4 Array.isArray() 函数:
- Array.isArray() 函数用于检测一个值是否是数组。它返回一个布尔值。例如:
Array.isArray([]); // 返回 true
Array.isArray({}); // 返回 false
3. 本地存储方式
cookie
- Cookies 是浏览器提供的一种存储数据的机制,用于在客户端存储少量的键值对数据。
- Cookies 可以通过
document.cookie
进行读取和设置。 - Cookies 的特点包括:
- 存储容量有限,一般为几 KB。
- 可以设置过期时间,可以是会话级的(关闭浏览器后失效)或具体的日期时间。
- 可以设置域名和路径,控制
Cookies
的作用范围。
- Cookies 的应用场景包括:
- 存储用户的登录状态,实现记住登录功能。
- 跟踪用户行为,进行统计和分析。
- 但是 Cookies 存在一些限制,如存储容量小、每次请求都会携带到服务器等。
Web Storage(localStorage 和 sessionStorage)
Web Storage 提供了比 Cookies 更大的存储容量,并且在客户端存储的数据不会随着每次请求被发送到服务器。
Web Storage 分为两种类型:localStorage
和sessionStorage
。
- localStorage:
- 存储容量较大,一般为几 MB。
- 数据在浏览器关闭后仍然存在,除非显式删除。
- 可以通过
localStorage.setItem(key, value)
、localStorage.getItem(key)
、localStorage.removeItem(key)
等方法进行读取和设置。
- sessionStorage:
- 存储容量与
localStorage
相同。- 数据在当前会话(窗口或标签页)关闭后即被删除。
- 可以通过
sessionStorage.setItem(key, value)
、sessionStorage.getItem(key)
、sessionStorage.removeItem(key)
等方法进行读取和设置。
- Web Storage 的应用场景包括:
- 存储用户的偏好设置和个性化配置。
- 缓存数据,提高页面加载速度。
- 在不同页面之间共享数据。
indexedDB
- IndexedDB 是一种客户端数据库,提供了存储结构化数据的能力。
- IndexedDB 支持事务操作,可以执行增、删、改、查等操作,并且支持索引。
- 存储容量较大,一般为几十 MB 到几百 MB。
- IndexedDB 的 API 较为复杂,需要进行异步操作。
- IndexedDB 的应用场景包括:
- 存储大量结构化数据,如离线应用的数据。
- 需要执行复杂查询操作的场景。
4.JS 模块化方案
CommonJS 和 ES6 Module 的使用和区别
CommonJS 是一种用于服务器端的模块化方案,主要在 Node.js 中使用。它使用 require 函数来加载模块,使用 module.exports 或 exports 导出模块。CommonJS 模块是同步加载的,它会阻塞后续代码的执行,直到模块加载完成。这种同步加载的特性使得 CommonJS 模块非常适合在服务器端环境中使用。
示例:
// 导入模块
const moduleA = require('./moduleA');// 导出模块
module.exports = {foo: 'Hello',bar: 'World'
};
ES6 模块是 ECMAScript 6 引入的官方标准模块化方案,它使用
import
和export
关键字进行模块的导入和导出。ES6 模块是静态加载的,它在编译时就能确定模块的依赖关系,因此具有更好的性能和可靠性。ES6 模块可以在浏览器环境和服务器端环境中使用。
示例:
// 导入模块
import moduleA from './moduleA';// 导出模块
export default {foo: 'Hello',bar: 'World'
};
区别:
- 语法不同:CommonJS 使用
require
和module.exports
,而 ES6 模块使用import
和export
。 - 加载方式不同:CommonJS 是同步加载模块,ES6 模块是静态加载模块。
- 静态分析:ES6 模块可以在编译时进行静态分析,可以优化代码的加载和执行过程。
- 默认导出:ES6 模块可以通过
export default
导出默认值,而 CommonJS 模块没有默认导出的机制。 - 动态导入:ES6 模块支持动态导入,可以根据条件来动态加载模块,而 CommonJS 不支持。
在实际开发中,如果你在浏览器环境中使用,可以优先选择使用 ES6 模块。而在服务器端使用 Node.js,则可以选择使用 CommonJS。如果你在项目中需要同时使用两种模块化方案,可以通过工具进行转换,如 Babel 等。
5.Webpack 常使用的 Loader 和 Plugin
Webpack 是一个模块打包工具,它可以将各种资源文件打包成静态资源,用于在浏览器中加载。在 Webpack 中,常用的 Loader 和 Plugin 可以扩展其功能和处理各种类型的文件。
Loader 是用于转换文件的加载器,在模块的加载过程中对文件进行处理。常见的 Loader 有:
- Babel Loader: 用于将 ES6+ 语法转换为浏览器可识别的 JavaScript。
- CSS Loader: 用于加载和处理 CSS 文件,支持 CSS 模块化、自动添加浏览器前缀等功能。
- Style Loader: 用于将 CSS 代码注入到 HTML 页面中,使其生效。
- File Loader: 用于加载和处理文件,如图片、字体等,可以将文件拷贝到输出目录并生成对应的 URL。
- URL Loader: 类似于 File Loader,但可以将小文件转换为 Data URL,减少 HTTP 请求。
- PostCSS Loader: 用于在构建过程中对 CSS 进行转换和优化,例如使用 Autoprefixer 添加浏览器前缀、压缩 CSS 等。
Plugin 是用于扩展 Webpack 功能的插件,可以在整个构建过程中执行自定义的任务。常见的 Plugin 有:
- HtmlWebpackPlugin: 自动生成 HTML 文件,并自动将打包后的资源引入到 HTML 中。
- CleanWebpackPlugin: 清理构建目录中的旧文件,确保每次构建前都是干净的状态。
- MiniCssExtractPlugin: 将 CSS 从 JavaScript 中提取出来,生成单独的 CSS 文件。
- DefinePlugin: 在构建过程中定义全局常量,可用于区分开发环境和生产环境。
- CopyWebpackPlugin: 将指定的文件或目录复制到构建目录中,常用于复制静态资源。
- UglifyJsPlugin: 压缩 JavaScript 代码,减小文件体积,提高加载速度。
6.HTTP 缓存
图解 HTTP 缓存
7.call、apply、bind
call
, apply
, 和 bind
是 JavaScript 中用于改变函数执行上下文(即函数内部的 this
值)的方法。
call 方法:
- 语法:
function.call(thisArg, arg1, arg2, ...)
- 功能:
call
方法会立即调用函数,并将函数的执行上下文(this
值)设置为 thisArg 参数指定的值,同时可以传递多个参数作为函数的参数进行调用。
示例:
function greet(name) {console.log(`Hello, ${name}! My name is ${this.name}.`);
}const person = {name: 'John',
};greet.call(person, 'Alice');
// 输出: Hello, Alice! My name is John.
apply 方法:
- 语法:
function.apply(thisArg, [argsArray])
- 功能:
apply
方法与 call 方法类似,区别在于它接受一个数组(或类数组对象)作为参数列表,而不是单独的参数。
示例:
function greet(name) {console.log(`Hello, ${name}! My name is ${this.name}.`);
}const person = {name: 'John',
};greet.apply(person, ['Alice']);
// 输出: Hello, Alice! My name is John.
bind 方法:
- 语法:
function.bind(thisArg, arg1, arg2, ...)
- 功能:
bind
方法创建一个新的函数,并将原函数的执行上下文(this
值)设置为thisArg
参数指定的值,同时可以传递多个参数作为新函数的参数。不同于call
和apply
,bind
不会立即执行函数,而是返回一个绑定了执行上下文的新函数。
示例:
function greet(name) {console.log(`Hello, ${name}! My name is ${this.name}.`);
}const person = {name: 'John',
};const greetPerson = greet.bind(person);
greetPerson('Alice');
// 输出: Hello, Alice! My name is John.
7.函数柯里化
函数柯里化(Currying)是一种将接受多个参数的函数转换为一系列接受单个参数的函数的技术。
通过函数柯里化,我们可以更灵活地处理函数的参数,提高代码的可读性、复用性和可维护性。
- 在函数柯里化中,通过将多个参数的函数转化为一系列只接受一个参数的函数来实现。每个接受单个参数的函数都会返回一个新的函数,该函数接受下一个参数,并继续返回新的函数。这个过程可以继续进行,直到接受了所有的参数,然后执行最终的函数调用。
- 函数柯里化的优点之一是可以创建更具复用性和灵活性的函数。通过部分应用函数的参数,可以轻松创建新的函数,并在需要时进行调用。
示例:
function add(a, b, c) {return a + b + c;
}// 将 add 函数柯里化
function curryAdd(a) {return function(b) {return function(c) {return add(a, b, c);}}
}// 使用柯里化的函数进行调用
const result = curryAdd(1)(2)(3);
console.log(result); // 输出: 6
在上面例子中,我们通过
curryAdd
函数将add
函数进行柯里化。通过传递参数1
、2
和3
,我们分别得到了一个新的函数,并最终执行了函数调用,得到了结果6
。
函数柯里化在实际开发中的应用场景,比如:
- 部分应用函数的参数,以便在稍后的时间点上进行调用。
- 创建可以复用的函数模板,通过预定义一些参数,生成特定功能的函数。
- 支持函数组合,将多个函数组合在一起,形成新的函数。
- 支持函数的柯里化和偏函数应用。
8.什么是 js 的闭包?有什么作用?
闭包(Closure)是指一个函数能够访问并操作其词法作用域外部的变量的能力。具体来说,闭包是由函数以及函数内部能够访问的变量组合而成的包裹(Closure)。
闭包的主要特点包括:
- 函数内部可以访问外部函数的变量和参数。
- 外部函数执行完毕后,其内部变量不会被销毁,仍然可以被内部函数访问。
- 闭包可以捕获并保存外部函数的作用域,使得外部函数的变量在内部函数执行时仍然可用。
闭包的作用有以下几个方面:
- 保护变量:闭包可以保护变量不被外部访问和修改,实现了数据的私有化,增加了程序的安全性。
- 保存状态:通过闭包可以创建函数工厂,每次调用函数时都可以保留一部分上下文状态。这对于需要记住之前状态的函数非常有用,比如计数器、迭代器等。
- 实现函数的部分应用:通过闭包可以固定函数的部分参数,返回一个接受剩余参数的新函数。这样可以实现函数的复用和定制。
- 模块化开发:使用闭包可以将相关的变量和函数封装在一个作用域内,实现模块化开发,避免变量污染和命名冲突。
示例:
function outerFunction() {var outerVariable = 'Hello';function innerFunction() {console.log(outerVariable);}return innerFunction;
}var closure = outerFunction();
closure(); // 输出: Hello
在上面的例子,
innerFunction
是一个闭包,它可以访问outerFunction
中的变量outerVariable
,即使在outerFunction
执行完毕后依然可以访问。