typeof、instanceof 检测数据类型
typeof
typeof val | Result |
---|---|
Undefined | “undefined” |
Null | “object” |
Boolean | “boolean” |
Nubmer | “number” |
String | “string” |
Symbol | “symbol” |
BigInt | “bigint” |
Object (does not implement [[Call]]) | “object” |
Ojbect (implements [[Call]]) | “function” |
Instanceof
object instanceof constructor
检测构造函数的prototype
属性是否出现在某个实例对象的原型链上
注意:一个对象的原型链是会改变的
如果obj instanceof Foo
返回 true
,并不意味着该表达式会永远返回true
,因为:
Foo.prototype
属性的值可能会改变,改变之后的值可能不存在于obj
的原型链上,此时原表达式的值就会为false
- 对象obj的原型链也可能改变,借助
__proto__
伪属性,可以改变对象的原型链。obj.__proto__={}
,则obj instanceof Foo
返回false
1 | function A() {} |
数据的存储形式-堆栈
栈
- 自动分配的内存空间,在代码执行过程中自动释放。
- 在栈区内存会创建一个JS代码执行的环境,作用域、函数的调用都在栈内存中执行。
- JS的基本数据类型,占用空间大小固定,其值是直接保存在栈内存中,按值访问。
- 对于Ojbect的引用类型,其指针存储在栈内存中,指向堆内存的实际地址,通过引用访问
堆
动态分配堆内存,大小不定,不会自动释放。
堆内存中存储实际对象,在栈内存中存储对象的指针。对象的访问是按引用访问的
在堆区的内存不会自动释放,需要实现垃圾回收机制(GC)
因为在栈区指向的变量等是通过值访问的,当前作用域销毁后变量也就随之销毁,而使用引用访问是堆区变量,在作用域消失后,可能在外层作用域仍然存在引用,不能直接销毁,此时就需要判断此变量是否属于不再需要的变量,从而决定是否进行内存回收。
在Js中主要有 引用计数 和 标记清除 两种垃圾回收算法
深、浅拷贝
递归方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// 仅 实现 数组、对象的深拷贝,其它 例如Date,Fucntion, RegExp
function cloneDeep(obj) {
let objClone = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === 'object') {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
if(obj[key] && type typeof obj[key] === 'object') {
objClone[key] = cloneDeep(obj[key]);
}else {
objClone[key] = obj[key];
}
}
}
}
return objClone;
}Object.assign(), 仅深拷贝对象的一级属性
$.extend(true,{},{a:1,b:2})
loadsh.cloneDeep()
编码、解码使用场景
在URL地址,不允许出现非ASCII字符,如果URL地址中包含中文字符,就必须堆中文字符进行编码(转义)
encodeURI() / encodeURIComponent()
encodeURI 通常用于转码整个 URI, 其不会进行编码的字符包括
; , / ? : @ & = + $ - _ . ! ~ * ' ( ) #
encodeURIComponent ,仅用于转码 URI的组成部分(?后面的参数), 其不会进行编码的字符包括
- _ . ! ~ * ' ( )
如果使用 encodeURIComponent 对整个URL进行编码,
/ :
字符会被编码; 使用 encodeURL 对整个URL进行编码,& + =
不会别编码,这GET、POST请求中是特殊字符,应该被编码。所以正确方法,使用 encodeURIComponent,仅对参数进行编码1
2
3
4
5
6
7
8
9let url = "https://developer.mozilla.org/en-US/search?q=闭包&a=123";
console.log(encodeURI(url)); // https://developer.mozilla.org/en-US/search?q=%E9%97%AD%E5%8C%85
console.log(encodeURIComponent(url)); // https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fsearch%3Fq%3D%E9%97%AD%E5%8C%85
console.log(
"https://developer.mozilla.org/en-US/search?q=" +
encodeURIComponent("闭包&a=123")
); // https://developer.mozilla.org/en-US/search?q=%E9%97%AD%E5%8C%85%26a%3D123- 为避免服务器收到不可预知的请求,对任何用户的输入作为URI部分的内容都需要encodeURIComponent 进行转义。例如,用户可能输入
闭包&a=123
作为参数q的值,如果不对此内容进行转义,服务器得到的将是q=闭包&a=123
,即两个键值对(q=闭包,a=123),而不是一个键值对(q=闭包&a=123)
- 为避免服务器收到不可预知的请求,对任何用户的输入作为URI部分的内容都需要encodeURIComponent 进行转义。例如,用户可能输入
隐式类型转换
隐式类型转换 是在一定场景下,js运行环境会自动调用👇🏻几个方法,尝试转换成期望的数据类型
ToString, 其他类型的值转换为字符串类型
- null, “null”
- undefined,”undefined”,
- 布尔类型,”true”, “false”
- 数字类型,10,”10”, 1e21 , “1e+21”
- 数组,相当于调用
Array.prototype.join()
方法,[1,2,3] 转换 “1,2,3”, 空数组[]转换为空字符串’’, 数组中的null,undefined,会被当做""
空字符串处理 - 对象,相当于调用
Object.prototype.toString()
,返回”[object Object]”
ToNumber
- null, 0
- undefined, NaN
- 字符串,纯数字形式,转换为对应的数字,空字符串转换为0, 否则按失败处理,转换为 NaN
- 数组,首先会被转换为原始类型(ToPrimitive),然后在根据转换后的原始类型处理
ToBoolean
js中的假值,只有
false
,null
,undefined
,""
,0
,NaN
, 其它值转化为布尔值都为trueToPrimitive, 对象类型(对象、数组)转化为原始类型的操作
- 当对象类型需要转化为原始类型时,会向查找对象的
valueOf
方法,如果valueOf()
方法返回原始类型的值,则结果就是该值 - 如果对象的
valueOf()
不存在,或者valueOf()
方法返回的不是原始类型的值,则会去调用对象的toString()
方法,且遵循对象的ToString
规则,则toString()
的返回值作为ToPrimitive
的结果
- 当对象类型需要转化为原始类型时,会向查找对象的