扩展运算符
扩展运算符是ES6中新增的一个语法,它可以将一个数组或者类数组对象展开成一个用逗号分隔的参数序列。在函数调用时,我们可以使用扩展运算符来传递一个数组或者类数组对象作为函数的参数。在数组字面量中,我们也可以使用扩展运算符来将一个数组或者类数组对象展开成一个新的数组。
下面是一个使用扩展运算符的例子:
function sum(a,b,c){
return a+b+c;
}
const arr=[1,2,3];
console.log(sum(...arr));// 6
const arr1=[4,5,6];const arr2=[1,2,3,...arr1];
console.log(arr2);// [1, 2, 3, 4, 5, 6]
在这个例子中,我们定义了一个sum函数,它接受三个参数。我们使用扩展运算符将数组arr展开成一个用逗号分隔的参数序列,然后将这个参数序列传递给sum函数。在第二个例子中,我们使用扩展运算符将数组arr1展开成一个用逗号分隔的参数序列,然后将这个参数序列与数组[1, 2, 3]合并成一个新的数组arr2。
for of 和 for in用法的区别
for...of循环和for...in循环都是用来遍历数组或者对象的,但是它们的用法和作用是不同的。
for...of循环是ES6中新增的一个语法,它可以用来遍历可迭代对象(包括数组、字符串、Map、Set等)。在每次迭代中,for...of循环会将可迭代对象的下一个值赋值给一个变量,然后执行循环体中的语句。例如:
const arr=[1,2,3];
for(const item of arr){
console.log(item);
}
在这个例子中,我们定义了一个数组arr,然后使用for...of循环遍历这个数组。在每次迭代中,for...of循环会将数组的下一个值赋值给变量item,然后执行循环体中的语句。这样,我们就可以依次输出数组中的每个元素。
for...in循环是用来遍历对象的,它会枚举对象的所有可枚举属性(包括自身属性和继承属性)。在每次迭代中,for...in循环会将对象的下一个属性名赋值给一个变量,然后执行循环体中的语句。例如:
const obj={name:'John',age:30};
for(const key in obj){
console.log(key,obj[key]);
}
在这个例子中,我们定义了一个对象obj,然后使用for...in循环遍历这个对象。在每次迭代中,for...in循环会将对象的下一个属性名赋值给变量key,然后执行循环体中的语句。这样,我们就可以依次输出对象的所有属性名和属性值。
需要注意的是,for...in循环会枚举对象的所有可枚举属性,包括自身属性和继承属性。如果你只想枚举对象的自身属性,可以使用Object.keys()方法、Object.getOwnPropertyNames()方法或者Reflect.ownKeys()方法来获取对象的所有自身属性,然后使用for...of循环遍历这个数组。例如:
constobj={name:'John',age:30};
for(const key of Object.keys(obj)){
console.log(key,obj[key]);
}
在这个例子中,我们使用Object.keys()方法获取对象obj的所有自身属性名,然后使用for...of循环遍历这个数组。在每次迭代中,for...of循环会将数组的下一个值赋值给变量key,然后执行循环体中的语句。这样,我们就可以依次输出对象的所有自身属性名和属性值。
Object.keys()方法、Object.getOwnPropertyNames()方法和Reflect.ownKeys()三种方法的区别是什么
Object.keys()方法、Object.getOwnPropertyNames()方法和Reflect.ownKeys()方法都可以用来获取对象的所有自身属性名,但是它们的返回结果有所不同。
Object.keys()方法返回一个由对象的所有可枚举属性名组成的数组。
Object.getOwnPropertyNames()方法返回一个由对象的所有自身属性名组成的数组,包括不可枚举属性。
Reflect.ownKeys()方法返回一个由对象的所有自身属性名和Symbol类型的属性名组成的数组,包括不可枚举属性和Symbol类型的属性名。
需要注意的是,for...of循环只能用来遍历可迭代对象,不能用来遍历普通对象。如果你想遍历普通对象的属性,可以使用上面提到的三种方法之一来获取对象的所有自身属性名,然后使用for...of循环遍历这个数组。
不可枚举属性是什么
在JavaScript中,对象的属性可以分为可枚举属性和不可枚举属性。可枚举属性是指那些可以通过for...in循环枚举出来的属性,而不可枚举属性则是指那些不能通过for...in循环枚举出来的属性。
在对象字面量中定义的属性默认是可枚举的,而通过Object.defineProperty()方法定义的属性默认是不可枚举的。你可以通过在Object.defineProperty()方法的第三个参数中设置enumerable属性为false来将属性设置为不可枚举的。例如:
const obj={};
Object.defineProperty(obj,'name',{value:'John',enumerable:false,});
for(const key in obj){
console.log(key,obj[key]);
}
在这个例子中,我们定义了一个空对象obj,然后使用Object.defineProperty()方法定义了一个名为name的属性,并将enumerable属性设置为false。在for...in循环中,我们无法枚举出这个属性,因为它是不可枚举的。
需要注意的是,不可枚举属性并不是私有属性,它们仍然可以通过对象的其他方法来访问和修改。如果你想将一个属性既设置为不可枚举的,又设置为私有属性,可以使用Symbol类型的属性名来定义这个属性。因为Symbol类型的属性名是唯一的,所以它们不会被意外地访问或修改。
可选链操作符
可选链操作符是ES2020中新增的一个语法,它可以用来简化访问对象属性或方法时的空值判断。在使用可选链操作符时,我们可以使用问号(?)来代替点号(.)来访问对象的属性或方法。如果对象的属性或方法不存在,那么JavaScript就会返回undefined,而不是抛出TypeError错误。
下面是一个使用可选链操作符的例子:
constobj={name:'John',age:30,};
console.log(obj?.name);// 'John'console.log(obj?.address?.city);// undefined
在这个例子中,我们定义了一个对象obj,它有一个name属性和一个age属性。我们使用可选链操作符来访问obj对象的name属性和address属性的city属性。在第一个console.log()中,我们成功地访问了obj对象的name属性,并输出了它的值。在第二个console.log()中,我们尝试访问obj对象的address属性的city属性,但是address属性不存在,所以JavaScript返回了undefined。
需要注意的是,可选链操作符只能用来访问对象的属性或方法,不能用来访问变量或函数。如果你想访问一个变量或函数,仍然需要使用传统的空值判断方法,例如:
const obj = {
name: 'John',
age: 30,
};
const func = obj?.func;
if (func) {
func();
}
在这个例子中,我们尝试访问obj对象的func属性,但是func属性不存在,所以JavaScript返回了undefined。我们使用if语句来判断func是否存在,如果存在就调用它。这样,我们就避免了在func不存在时抛出TypeError错误的问题。
BigInt类型
在JavaScript中,Number类型的数据是有范围限制的,它的最大值是2的53次方减1,也就是9007199254740991。如果你需要处理更大的整数,可以使用BigInt类型。
BigInt类型是ES2020中新增的一个数据类型,它可以表示任意精度的整数。在JavaScript中,我们可以使用n后缀来表示一个BigInt类型的数据。例如:
consta=9007199254740991n;
constb=BigInt('9007199254740991');
console.log(a===b);// true
在这个例子中,我们定义了两个BigInt类型的数据a和b,它们的值都是9007199254740991。我们使用n后缀和BigInt()函数来表示这些数据。在最后一行,我们使用===运算符来比较a和b的值,发现它们是相等的。
需要注意的是,BigInt类型的数据和Number类型的数据是不同的,它们不能混合使用。如果你想将一个BigInt类型的数据转换为Number类型的数据,可以使用Number()函数来进行转换。如果你想将一个Number类型的数据转换为BigInt类型的数据,可以使用BigInt()函数来进行转换。例如:
const a = 9007199254740991n;
const b = Number(a);
console.log(typeof a, typeof b); // 'bigint' 'number'
const c = 9007199254740991;
const d = BigInt(c);
console.log(typeof c, typeof d); // 'number' 'bigint'
在这个例子中,我们将一个BigInt类型的数据a转换为Number类型的数据b,将一个Number类型的数据c转换为BigInt类型的数据d。在第一个console.log()中,我们输出了a和b的类型,发现它们分别是'bigint'和'number'。在第二个console.log()中,我们输出了c和d的类型,发现它们分别是'number'和'bigint'。
注意:BigInt数据没办法和Number数据直接进行运算,需要进行转换为同一种数据
instanceof
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
typeof
typeof 运算符返回一个字符串,表示操作数的类型。
数据类型有哪些
JavaScript中的数据类型包括:
基本数据类型:Number、String、Boolean、Null、Undefined、Symbol(ES6新增)。
引用数据类型:Object、Array、Function、Date、RegExp等。
特殊数据类型:BigInt(ES2020新增)。
其中,基本数据类型是指那些不可变的数据类型,它们的值在内存中占据固定的空间大小,可以直接存储在栈内存中。引用数据类型是指那些可变的数据类型,它们的值在内存中占据不固定的空间大小,需要存储在堆内存中,并通过引用来访问。特殊数据类型是指那些特殊的数据类型,它们的值可以表示任意精度的整数,需要使用特殊的语法来表示。
globalThis
在JavaScript中,globalThis是一个全局对象,它可以用来访问全局作用域中的变量和函数。在浏览器中,globalThis指向window对象;在Node.js中,globalThis指向global对象。
globalThis是ES2020中新增的一个语法,它可以用来解决在不同的JavaScript环境中访问全局对象的问题。在ES5及之前的版本中,访问全局对象的方法是不统一的,需要根据不同的环境来选择不同的方法。在ES6中,引入了let和const关键字,它们可以用来定义块级作用域,但是它们并不能解决访问全局对象的问题。在ES2020中,我们可以使用globalThis来访问全局对象,而不需要考虑不同的JavaScript环境。
下面是一个使用globalThis的例子:
globalThis.name='John';
console.log(name);// 'John'
console.log(globalThis.name);// 'John'
console.log(window.name);// 'John'(在浏览器中)
console.log(global.name);// 'John'(在Node.js中)
在这个例子中,我们使用globalThis来定义一个全局变量name,并将它的值设置为'John'。然后,我们使用不同的方法来访问这个全局变量,包括直接访问、访问globalThis对象和访问window对象或global对象。在不同的JavaScript环境中,这些方法的返回结果可能会有所不同,但是它们都可以用来访问全局变量name。
需要注意的是,globalThis是一个只读属性,它不能被重新赋值。如果你想定义一个全局变量,应该使用var、let或const关键字来定义。
Promise
在JavaScript中,Promise是一种异步编程的解决方案,它可以用来处理异步操作的结果。Promise对象代表一个异步操作,它可以处于三种状态之一:pending(进行中)、fulfilled(已成功)和rejected(已失败)。当异步操作完成时,Promise对象会从pending状态转变为fulfilled或rejected状态,并执行相应的回调函数。
闭包
闭包是指在一个函数内部定义的函数可以访问该函数的变量和参数,即使在该函数已经返回之后。这是因为内部函数形成了一个闭包,它可以访问外部函数的作用域链。闭包可以用来创建私有变量和方法,以及实现一些高级的编程模式。
例如,考虑以下代码:
functionouterFunction(){
varouterVariable='I am outside!';
functioninnerFunction(){
console.log(outerVariable);
}
return innerFunction;
}
var inner=outerFunction();
inner();// 输出 'I am outside!'
在这个例子中,outerFunction返回了innerFunction,而innerFunction可以访问outerFunction中定义的outerVariable变量。即使outerFunction已经返回了,innerFunction仍然可以访问outerVariable变量,因为它形成了一个闭包。
作用域链是什么
作用域链是指在JavaScript中,每个函数都有一个作用域链,它用于查找变量和函数的定义。作用域链由当前函数的变量对象和所有外部函数的变量对象组成,它决定了哪些变量和函数可以在当前函数中访问。
当一个函数被调用时,JavaScript引擎会创建一个新的执行上下文,并将其添加到执行上下文栈中。每个执行上下文都有一个变量对象,它包含了当前函数的参数、局部变量和内部函数的引用。当JavaScript引擎需要查找一个变量或函数时,它会首先在当前函数的变量对象中查找,如果找不到,就会继续在外部函数的变量对象中查找,直到找到该变量或函数为止。
作用域链的顶端是全局作用域,它包含了所有全局变量和函数的定义。当JavaScript引擎需要查找一个变量或函数时,如果在作用域链的任何一个环节中找不到该变量或函数,就会抛出一个ReferenceError异常。
变量对象是什么
在JavaScript中,每个函数都有一个变量对象,它包含了当前函数的参数、局部变量和内部函数的引用。变量对象是在函数被调用时创建的,它用于存储函数内部的所有变量和函数的定义。当JavaScript引擎需要查找一个变量或函数时,它会首先在当前函数的变量对象中查找,如果找不到,就会继续在外部函数的变量对象中查找,直到找到该变量或函数为止。
变量对象的属性分为两种类型:数据属性和访问器属性。数据属性包含一个值,可以通过赋值运算符来修改。访问器属性包含一个getter函数和一个setter函数,可以用来计算属性的值。
如果你想了解更多关于变量对象的知识,可以参考以下文章:
Array.isArray()的作用
Array.isArray()是一个用于判断一个值是否为数组的方法。它接受一个参数,如果该参数是一个数组,则返回true,否则返回false。
例如,以下代码将返回true:
Array.isArray([1,2,3]);
而以下代码将返回false:
Array.isArray('hello');
Array.isArray()方法可以用于检查函数的参数是否为数组,以及在编写通用函数时检查返回值是否为数组。
异步编程是什么
异步编程是一种编程模式,它允许程序在等待某些操作完成时继续执行其他操作。在异步编程中,程序不会阻塞等待操作完成,而是会在操作完成后执行回调函数或触发事件来处理操作的结果。
异步编程通常用于处理一些耗时的操作,例如网络请求、文件读写等。在传统的同步编程中,程序会在等待这些操作完成时一直阻塞,直到操作完成后才能继续执行。这种方式会导致程序的响应速度变慢,因此异步编程成为了一种更加高效的编程方式。
在JavaScript中,异步编程通常使用回调函数、Promise和async/await等方式来实现。回调函数是一种最基本的异步编程方式,它允许程序在操作完成后执行一个回调函数来处理操作的结果。Promise是一种更加高级的异步编程方式,它允许程序使用链式调用的方式来处理异步操作的结果。async/await是ES2017中引入的一种异步编程方式,它允许程序使用类似同步编程的方式来处理异步操作的结果。
异步操作有哪些
在JavaScript中,常见的异步操作包括:
定时器:使用setTimeout()和setInterval()函数可以在一定时间后执行回调函数或定期执行回调函数。
网络请求:使用XMLHttpRequest对象或fetch API可以向服务器发送请求并在响应返回后执行回调函数。
事件处理:使用addEventListener()函数可以监听DOM事件并在事件触发后执行回调函数。
文件读写:使用File API可以读取和写入本地文件,并在读取或写入完成后执行回调函数。
Promise:Promise是一种用于处理异步操作的对象,它可以在异步操作完成后执行回调函数,并且可以链式调用多个异步操作。
async/await:async/await是ES2017中引入的一种异步编程方式,它允许程序使用类似同步编程的方式来处理异步操作的结果。
在实际开发中,异步操作是非常常见的,因为它可以提高程序的响应速度和性能。因此,了解异步操作的相关知识是非常重要的。
同步编程是什么
同步编程是一种编程模式,它要求程序按照顺序依次执行每个操作,直到操作完成后才能继续执行下一个操作。在同步编程中,程序会一直阻塞等待当前操作完成后才能继续执行下一个操作。这种方式会导致程序的响应速度变慢,因此异步编程成为了一种更加高效的编程方式。
贪婪模式和非贪婪模式
在正则表达式中,贪婪和非贪婪是指匹配模式的行为。贪婪模式会尽可能多地匹配字符,而非贪婪模式则会尽可能少地匹配字符。
例如,考虑以下字符串:
<p>Hello</p>
我们想要匹配<p>标签和</p>标签之间的内容。如果我们使用贪婪模式,我们可以使用以下正则表达式:
/<p>(.*)<\/p>/
这将匹配整个字符串,因为.*会尽可能多地匹配字符。如果我们使用非贪婪模式,我们可以使用以下正则表达式:
/<p>(.*?)<\/p>/
这将只匹配<p>标签和</p>标签之间的内容,因为.*?会尽可能少地匹配字符。
在你的代码中,如果你想使用非贪婪模式,可以在*或+后面添加?来表示非贪婪模式。例如,你可以使用以下正则表达式来匹配所有的a标签:
/<a.*?>(.*?)<\/a>/
这将匹配所有的a标签,并且只会匹配标签之间的内容。
.?和(.?)的区别
在正则表达式中,.?和(.?)都表示非贪婪模式,它们会尽可能少地匹配字符。它们的区别在于,.?匹配任意字符,而(.?)只匹配括号内的表达式。
例如,考虑以下字符串:
我们想要匹配<p>标签和</p>标签之间的内容。如果我们使用.*?,我们可以使用以下正则表达式:
/<p>(.*?)<\/p>/
这将只匹配<p>标签和</p>标签之间的内容,因为(.?)只匹配括号内的表达式。如果我们使用.?,我们可以使用以下正则表达式:
/<.*?>(.*?)<\/.*?>/
这将匹配任意标签和标签之间的内容,因为.*?匹配任意字符。
因此,如果你只想匹配括号内的表达式,应该使用(.?),而如果你想匹配任意字符,应该使用.?。
Promise的优点
Promise的优点包括:
可以避免回调地狱:使用Promise可以避免回调地狱,即多层嵌套的回调函数,使代码更加清晰和易于维护。
可以链式调用多个异步操作:使用Promise可以链式调用多个异步操作,使代码更加简洁和易于理解。
可以处理异步操作的结果:使用Promise可以在异步操作完成后执行回调函数,并且可以处理异步操作的结果,例如成功、失败或进度等。
可以处理多个异步操作的结果:使用Promise.all()方法可以处理多个异步操作的结果,并在所有异步操作完成后执行回调函数。
可以处理异步操作的错误:使用Promise.catch()方法可以处理异步操作的错误,并在发生错误时执行回调函数。
因此,Promise是一种非常强大和实用的异步编程方式,它可以提高程序的响应速度和性能,同时也可以使代码更加清晰和易于维护。
常见的Math方法
JavaScript中的Math对象提供了一些常用的数学方法,包括:
Math.abs(x):返回x的绝对值。
Math.ceil(x):返回大于等于x的最小整数。
Math.floor(x):返回小于等于x的最大整数。
Math.round(x):返回最接近x的整数。
Math.max(x1, x2, ...):返回一组数中的最大值。
Math.min(x1, x2, ...):返回一组数中的最小值。
Math.pow(x, y):返回x的y次幂。
Math.sqrt(x):返回x的平方根。
Math.random():返回一个0到1之间的随机数。
例如,以下代码将返回2:
Math.abs(-2);
以下代码将返回3:
Math.ceil(2.3);
以下代码将返回2:
Math.floor(2.9);
以下代码将返回3:
Math.round(2.5);
以下代码将返回5:
Math.max(1,3,5);
以下代码将返回1:
Math.min(1,3,5);
以下代码将返回8:
Math.pow(2,3);
以下代码将返回3:
Math.sqrt(9);
以下代码将返回一个0到1之间的随机数:
Math.random();
这些方法可以用于处理各种数学计算,例如计算平均值、标准差、随机数等。
数组的常用方法
JavaScript中的数组提供了许多常用的方法,包括:
push():向数组末尾添加一个或多个元素,并返回新的长度。
pop():从数组末尾删除一个元素,并返回该元素的值。
shift():从数组开头删除一个元素,并返回该元素的值。
unshift():向数组开头添加一个或多个元素,并返回新的长度。
slice():返回数组的一个子数组。
splice():向数组中插入或删除元素。
concat():将两个或多个数组合并成一个新数组。
join():将数组中的所有元素转换为一个字符串。
indexOf():返回数组中第一个匹配元素的索引。
lastIndexOf():返回数组中最后一个匹配元素的索引。
forEach():对数组中的每个元素执行一次回调函数。
map():对数组中的每个元素执行一次回调函数,并返回一个新数组。
filter():返回一个新数组,其中包含符合条件的元素。
reduce():对数组中的每个元素执行一次回调函数,并返回一个累加值。
some():返回一个布尔值,表示数组中是否存在符合条件的元素。
every():返回一个布尔值,表示数组中的所有元素是否都符合条件。
对象的常用方法
JavaScript中的对象提供了许多常用的方法,包括:
Object.keys(obj):返回一个包含对象所有属性名的数组。
Object.values(obj):返回一个包含对象所有属性值的数组。
Object.entries(obj):返回一个包含对象所有属性名和属性值的二维数组。
Object.assign(target, ...sources):将一个或多个对象的属性复制到目标对象中,并返回目标对象。
Object.defineProperty(obj, prop, descriptor):定义一个新属性或修改一个已有属性的特性,并返回修改后的对象。
Object.getOwnPropertyDescriptor(obj, prop):返回指定属性的属性描述符。
Object.create(proto, [propertiesObject]):使用指定的原型对象和属性创建一个新对象,并返回新对象。
Object.freeze(obj):冻结一个对象,使其属性不可修改,并返回冻结后的对象。
Object.seal(obj):封闭一个对象,使其属性不可添加或删除,但属性值可以修改,并返回封闭后的对象。
Object.isExtensible(obj):判断一个对象是否可扩展。
Object.isFrozen(obj):判断一个对象是否被冻结。
Object.isSealed(obj):判断一个对象是否被封闭。
字符串的常用方法
JavaScript中的字符串提供了许多常用的方法,包括:
length:返回字符串的长度。
charAt(index):返回指定索引位置的字符。
charCodeAt(index):返回指定索引位置的字符的Unicode编码。
concat(str1, str2, ...):将两个或多个字符串合并成一个新字符串。
indexOf(substr, [start]):返回字符串中第一个匹配子串的索引。
lastIndexOf(substr, [start]):返回字符串中最后一个匹配子串的索引。
match(regexp):在字符串中搜索指定的正则表达式,并返回匹配结果。
replace(regexp/substr, replacement):在字符串中搜索指定的正则表达式或子串,并用指定的字符串替换匹配结果。
search(regexp):在字符串中搜索指定的正则表达式,并返回匹配结果的索引。
slice(start, [end]):返回字符串的一个子串。
split([separator], [limit]):将字符串分割成一个数组。
substr(start, [length]):返回从指定位置开始的指定长度的子串。
substring(start, [end]):返回字符串的一个子串。
toLowerCase():将字符串转换为小写。
toUpperCase():将字符串转换为大写。
trim():去除字符串两端的空格。