1、js都有哪些算数运算符?
js中一共有10种算数运算符:
加法运算符:x + y
减法运算符: x - y
乘法运算符: x * y
除法运算符:x / y
指数运算符:x ** y
余数运算符:x % y
自增运算符:++x 或者 x++
自减运算符:--x 或者 x--
数值运算符: +x
负数值运算符:-x
2、其中的加法运算符的作用分为哪两种?
加法运算和字符串拼接
运算子的不同,导致了不同的语法行为,这种现象称为“重载”(overload)。
3、对象转为原始类型的方法?
object.valueOf().toString(); // [object object]
4、为什么{} == {}为false?
两个复合类型(对象、数组、函数)的数据比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个地址。
5、为什么[] == ![]为true?
右边
[] == true
![] == false
false == 0
左边
[].valueOf().toString() == ""
"" == 0
6、遵循编码规范的好处
提高代码可读性,并有效的减少一些编码错误,利于后期的维护和扩展,利于团队开发。
Airbnb的编码规范
7、构造函数 new方法的实现原理是什么?
在调用 new 的过程中会发生以下:
- 创建一个空对象
- 链接到原型
- 绑定 this
- 返回新对象
function create() {
// 创建一个空的对象
let obj = new Object()
// 获得构造函数
let Con = [].shift.call(arguments)
// 链接到原型
obj.__proto__ = Con.prototype
// 绑定 this,执行构造函数
let result = Con.apply(obj, arguments)
// 确保 new 出来的是个对象
return typeof result === 'object' ? result : obj
}
8、遍历对象的属性的方法都有哪些?
-
Object.keys()遍历该对象的私有的可枚举的属性,返回一个数组。 -
Object.getOwnPropertyNames()遍历该对象的所有属性,包括不可枚举的属性,返回一个数组。 -
for in遍历私有的和原型上的所有可枚举的属性
一般情况下,几乎总是使用Object.keys()方法,遍历对象的属性,但是ES5以下需要polyfill。
9、Object实例对象的方法有哪些?
-
Object.prototype.valueOf():返回当前对象对应的值。 -
Object.prototype.toString():返回当前对象对应的字符串形式。 -
Object.prototype.toLocaleString():返回当前对象对应的本地字符串形式。 -
Object.prototype.hasOwnProperty():判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。 -
Object.prototype.isPrototypeOf():判断当前对象是否为另一个对象的原型。 -
Object.prototype.propertyIsEnumerable():判断某个属性是否可枚举。
10、属性描述对象都包括什么?
{
value: 123, // 属性值
writable: false,// 属性是否可写
enumerable: true, // 属性是否可枚举
configurable: false, // 描述对象是否可配置
get: undefined, // 取值函数
set: undefined, //存值函数
}
11、对象的拷贝
浅拷贝
Object.assign()- 展开运算符
…
浅拷贝只能拷贝第一层,更多层的就需要深拷贝了
深拷贝
可以用JSON.parse(JSON.stringify(object)),但该方法有局限性:
- 会忽略
undefined - 会忽略
symbol - 会忽略函数
- 不能解决循环引用的对象
let a = {
age: undefined,
sex: Symbol('female'),
jobs: function() {},
name: 'norma'
}
let b = JSON.parse(JSON.stringify(a))
console.log(b) // {name: "norma"}
如果你所需拷贝的对象含有内置类型并且不包含函数,可以使用 MessageChannel
function structuralClone(obj) {
return new Promise(resolve => {
const {port1, port2} = new MessageChannel();
port2.onmessage = ev => resolve(ev.data);
port1.postMessage(obj);
});
}
var obj = {a: 1, b: {
c: b
}}
// 注意该方法是异步的
// 可以处理 undefined 和循环引用对象
(async () => {
const clone = await structuralClone(obj)
})()
如果包括上面三种情况可以使用lodash深拷贝函数
12、创建一个数组为什么最好用字面量方式,而不是构造函数方式?
因为Array构造函数有一个很大的缺陷,就是不同的参数,会导致它的行为不一致。
13、会改变原数组的方法有哪些?
push(),pop(),shift(),unshift(),join(),reverse() ,splice() ,sort()
14、什么是包装对象?
指的是与数值、字符串、布尔值分别相对应的Number、String、Boolean三个原生对象。这三个原生对象可以把原始类型的值变成(包装成)对象。
var v1 = new Number(123);
var v2 = new String('abc');
var v3 = new Boolean(true);
15、包装对象的设计目的
首先是使得“对象”这种类型可以覆盖 JavaScript 所有的值,整门语言有一个通用的数据模型,其次是使得原始类型的值也有办法调用自己的方法。
16、Number对象的方法有哪些?
isInteger() 判断是否为整数
isNaN() 判断是否不是数字
parseInt() 转为整数,非数字开头,返回NaN
parseFloat() 转为浮点数,非数字开头,返回NaN
toString() 转为字符串
toFixed(num) 保留几位小数,默认参数为0,返回对应的字符串
toExponential(num) 转为科学计数法,返回对应的字符串
toPrecision(num) 转为指定位数的有效数字
17、slice()、substring()、substr()之前的区别?
- slice() 返回截取的字符串,不改变原数组或字符串,最多2个参数,起始位置和结束位置(不包括)
参数1大于参数2时,返回空字符串或者空数组 - substring() 和slice的参数一样,参数不是负数或者参数1大于参数2的特殊时候,和slice的用法一模一样。
参数1大于参数2时,参数互换位置 - substr() 参数为起始位置和截取的个数
18、Math对象的常用方法有哪些?
Math.abs():绝对值
Math.ceil():向上取整
Math.floor():向下取整
Math.max():最大值
Math.min():最小值
Math.pow():指数运算
Math.sqrt():平方根
Math.log():自然对数
Math.exp():e的指数
Math.round():四舍五入
Math.random():随机数
19、正则的惰性和贪婪性指的是什么?
- 惰性指的是exec()捕获到第一个就不再往下继续了,加修饰符g,,捕获全部
- 贪婪性指的是match() 默认情况下都是最大可能匹配,即匹配直到下一个字符不满足匹配规则为止
20、JSON对象的常用方法?
JSON.stringify() 将一个值转为 JSON 字符串
JSON.parse() 将 JSON 字符串转换成对应的值