js疑难治愈

typeof、instanceof 检测数据类型

typeof

ecma-262 / typeof operator

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function A() {}
function B() {}

let a = new A();
a instanceof A; // true, Object.getPrototypeOf(a) === A.prototype; A.protoptype.isPrototypeOf(a) 返回true;
A.prototype instanceof Object // true,

A.prototype = {}; // 设置 A.prototype 指向一个空对象
let a2 = new A();
a2 instanceof A; // true
a instanceof A; // fasle, A.prototype 指向了一个空对象,这个空对象不在a 的原型链上

B.prototype = new A(); // 继承
let a3 = new B();
a3 instanceof B; // true
a3 instancof A; // true, 因为 A.prototype 在 a3 的原型链上

数据的存储形式-堆栈

  • 自动分配的内存空间,在代码执行过程中自动释放。
  • 在栈区内存会创建一个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
    9
    let 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)

隐式类型转换

隐式类型转换 是在一定场景下,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, 其它值转化为布尔值都为true

  • ToPrimitive, 对象类型(对象、数组)转化为原始类型的操作

    • 当对象类型需要转化为原始类型时,会向查找对象的valueOf方法,如果valueOf()方法返回原始类型的值,则结果就是该值
    • 如果对象的valueOf()不存在,或者valueOf()方法返回的不是原始类型的值,则会去调用对象的toString()方法,且遵循对象的ToString规则,则toString()的返回值作为ToPrimitive的结果