1.js判断变量类型
typeof
可以判断一般类型。但无法准确识别对象。所有对象或类对象类型(null)都为"object",比如数组typeof [] == "object"
。JS数据类型在底层都是以二进制的形式表示的,二进制的前三位为 0 会被 typeof 判断为对象类型,而 null 的二进制位恰好都是 0 ,因此,null 被误判断为 Object 类型。typeof
与其他条件组合判断:typeof arr=="object" && !!arr.push
instanceof
可以判断具体对象类型。用来判断对象是否为某个构造函数的实例。[] instanceof Array==true
Object.prototype.toString.call()
可以判断任意变量类型。Object.prototype.toString.call([])=="[object Array]"
.constructor.name
可以判断变量类型(null
和undefined
除外)。true.constructor.name=="Boolean"
- 判断数组也可以用
Array.isArray(arr)
方法
2.数组常用方法
pop()
尾部删除,返回尾部元素,会改变原数组push()
尾部插入,会改变原数组unshift()
头部插入,会改变原数组shift()
头部删除 ,这两个别搞混。返回头部元素,会改变原数组join()
把数组元素放入字符串,使用指定的分隔符进行分割reverse()
倒序数组元素顺序,返回倒序后的新数组。会改变原数组splice()
删除元素,并向数组添加新元素。会改变原数组sort()
对数组对象进行排序—字符串排序按每一个英文字母先后/数字排序按字符串处理(实际上是每一位的排序),会改变原数组slice()
从开始和结束位置截取数组中的元素返回新数组concat()
连接(合并)两个数组arr.length=0
清空数组map()/find()/filter()/reduce()/forEach()/some()/every()
:ES6数组新方法。(every
:一假即假,some
:一真即真)
3.数组去重
indexOf/includes
循环去重:申明一个新新数组,判断新数组中是否包含当前项,若没有,则push- ES6 Set对象去重:
Array.from(new Set(arr))
- Object键值对去重:把数组的值存为key,判断
obj[arr[i]]
是否存在,若存在则重复。 - 利用ES6的数组
reduce
方法(第二个参数[]
为初始值):arr.reduce((unique,item) =>unique.includes(item)?unique:[...unique,item], []);
4.去除字符串首尾空格
str.trim()
- 正则:
str.replace(/(^\s*)|(\s*$)/g,"")
5.requestAnimationFrame
requestAnimationFrame()
方法用于代替使用定时器开发的动画。此方法的回调函数会在浏览器重绘之前调用。此方法的执行频率与显示器的刷新频率相关。回调函数执行次数通常是每秒60次,但在大多数浏览器中,回调函数执行次数通常与浏览器屏幕刷新次数相匹配。为了提高性能和电池寿命,因此在大多数浏览器里,当requestAnimationFrame()
运行在后台标签页或者隐藏的<iframe>
里时,requestAnimationFrame()
会被暂停调用以提升性能和电池寿命。
大部分显示器的刷新频率为每秒60次,也就是每次刷新间隔为16.7ms,我们在渲染动画时只有每一帧间隔时间<=16.7ms才能让用户觉得不卡顿。
6.引用类型常见有哪些对象
Object、Array、RegExp、Date、Function、Math、String、Number、Boolean
7.对象深拷贝、浅拷贝
对象引用:只引用对象,没有真正的复制。只复制引用(内存地址指向/栈内存),没有复制真正的值(堆内存),对其进行修改会影响原对象。
浅拷贝:只复制一层对象的属性。如果对象还有嵌套对象,则无法复制。如Object.assign()
深拷贝:复制了对象真正的值。对其任何操作都不会影响被拷贝的对象。
实现浅拷贝:
- 扩展运算符
- Object.assign
- 数组通过
slice()
的方法
let a = {
age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
//-------------------------------------------
let a = {
age: 1
}
let c = {...a}
c.age = 2
console.log(a.age) // 1
实现深拷贝:
- 递归浅拷贝(可行)。
- 深度遍历对象,递归嵌套对象,将其键值对赋值给另外一个新创建的对象,但性能堪忧。
- 使用JSON反序列化和序列化,性能最快:
JSON.parse(JSON.stringify(oldObj))
(缺点:只能深拷贝对象和数组,会忽略undefined和symbol,不能序列化函数,不能序列化循环引用的对象) - 第三方库如
jQuery.extend
Proxy
或Object.defineProperty
来拦截set
和get
就能阻止拷贝对象修改原对象(性能高,无缺点),深拷贝点此参考
注意:数组的slice方法和concat方法无法进行深拷贝,只能浅拷贝。因为嵌套对象或数组会被引用。对象的Object.assign()
方法同样如此。
8.判断两个对象是否相等
"a==b"
或者Object.is(a,b)
可以判断两个对象是否相等,但仅限于两个对象引用相同,是同一个对象。深浅拷贝对象无法判断。
若要判断两个不同引用的对象是否相等,得通过深度遍历及递归方法(递归时判断值是否是Object)进行值的判断(遍历及递归之前先通过Object.getOwnPropertyNames
拿到两个对象的所有键名,比较键名是否相等)。
这时候不能用JSON.stringify()
方法去比对对象,因为序列化之后,键是有序的,无法比较。
9.js变量类型
基本类型有六种: null
,undefined
,boolean
,number
,string
,symbol
其中 JS 的数字类型是浮点类型的,没有整型。
NaN
也属于number
类型,并且NaN
不等于自身。对于基本类型来说,如果使用字面量的方式,那么这个变量只是个字面量,只有在必要的时候才会转换为对应的类型。
typeof
对于基本类型,除了null
是object
,其他都可以显示正确的类型。(在 JS 的最初版本中,使用的是 32 位系统,为了性能考虑使用低位存储了变量的类型信息,000
开头代表是对象,然而null
表示为全零,所以将它错误的判断为object
)
引用类型:object
,function
,array
,map
,set
引用类型在使用过程中会遇到浅拷贝和深拷贝的问题。
typeof
对于引用类型,除了函数都会显示object
10.隐式类型转换
使用if条件判断或使用==/&&/||等运算符时会对变量进行隐式类型转换。
隐式类型转换时,除了 undefined
, null
, false
, NaN
, ''
, 0
, -0
,[]
,其他所有值都转为 true
,包括所有对象(这里注意空数组会被转为false)。
对象在隐式类型转换时,首先会调用其原型上的 valueOf
方法或 toString
方法。valueOf
优先于toString
。并且这两个方法你是可以重写的。
let a = {
valueOf() {
return 0;
},
toString() {
return '1';
},
}
1 + a // => 1
'1' + a // => '10'
//-------------------
let a = {
toString() {
return '1';
},
}
1 + a // => '11'
'1' + a // => '11'
只有当加法运算时,其中一方是字符串类型,就会把另一个也转为字符串类型。其他运算只要其中一方是数字,那么另一方就转为数字。并且加法运算会触发三种类型转换:将值转换为原始值,转换为数字,转换为字符串。
1 + '1' // '11'
2 * '2' // 4
[1, 2] + [2, 1] // '1,22,1'
// [1, 2].toString() -> '1,2'
// [2, 1].toString() -> '2,1'
// '1,2' + '2,1' = '1,22,1'
对于加号需要注意这个表达式 'a' + + 'b'
'a' + + 'b' // -> "aNaN"
// 因为 + 'b' -> NaN
// 你也许在一些代码中看到过 + '1' -> 1
console.log(+'1') // 1
console.log(-'1') // -1
console.log(+'a') // NaN
console.log(-'a') // NaN
console.log(+'') // 0
console.log(+[]) // 0
console.log(+true) // 1
console.log(+false) // 0
console.log(-true) // -1
console.log(-false) // -0
console.log(-false) // -0
console.log(-[]) // -0
console.log(-'') // -0
console.log(+[123]) // 123
console.log(+['123']) // 123
console.log(+[true]) // NaN
console.log(+[123,1]) // NaN
// 'a' + + 'b' 等同于 'a' + (+'b') 等同于 'a' + NaN
console.log('a' + (+'b')) // "aNaN"
console.log( 'a' + NaN) // "aNaN"
空数组会被转为false
[] == ![] // -> true
[]==false //true
11.++运算
++在前,返回值是新值
++在后,返回值是旧值
var a = -1
if(++a){ // 这里++a的值为新值0
console.log(666)
}else{
console.log(888)
}
// 结果为888
// ---------------------------------------
var a = -1
if(a++){ // 这里a++的值为旧值-1
console.log(666)
}else{
console.log(888)
}
// 结果为666
本文固定连接:https://code.zuifengyun.com/2020/03/1963.html,转载须征得作者授权。