关于js变量与计算的小测试: https://jsisweird.com/
    一、变量类型及判断
    1、typeof能判断几种类型
    1、除了null,其他原始类型值都能立马判断出来。
    2、判断是不是null,直接用 === null来判断。
    3、typeof 函数类型 得到function
    4、typeof 数组类型 得到 object( 数组也是一种对象 ,key值是有序的字符串)
    5、区别 array和object,可以用Object.prototype.toString.call来判断
    2、何时用==,合适用===
    最好都用===等,判断一个变量是undefined或者null的时候 用 ‘==’; 因为undefined和null互相两等;
    1、需要隐式转换的时候用 ==,比如后台返回的code类型不确定时
    2、不需要隐式转化时用 === ,+0 === -0 ;
    tip: NaN不与任何值相等,只能用isNaN判断(es6中可以用Object.is;Object.is(NaN,NaN)返回true)。
    编程语言精度问题,导致小数计算不精确

    1. console.log(0.1 + 0.2 === 0.3) // false

    3、值类型和引用类型的区别
    为什么会用两种值类型?原始类型的值大小有限存在栈内存中,引用类型大小不固定,存在堆内存中,这样有利于提升计算机对值的储存和读取的效率
    易错题: 一个变量的赋值,对于另一个原来与它共享引用的对象没有影响,如果是对其修改则会产生影响

    1. let obj1 = {
    2. x:100
    3. };
    4. let obj2 = obj1;
    5. obj2.x = 101;
    6. let x1 = obj1.x
    7. x1 = 102;
    8. console.log(obj2.x) // => 101;

    4、手写深拷贝
    核心思路:判断是否为引用值,过滤原型上的方法,递归给新对象赋值
    疏忽点: 原型上的方法也被for in遍历,所以要用hasOwnProperty来过滤

    1. function cloneDeep(origin){
    2. //先判断是否是原始值
    3. let type = typeof origin;
    4. if(type === 'object' && type !== null){
    5. let copy;
    6. //判断是对象还是数组
    7. if(Object.prototype.toString.call(origin) === '[object Object]'){
    8. copy = {}
    9. }else{
    10. copy = []
    11. }
    12. //循环遍历赋值
    13. for(let key in origin){
    14. if(origin.hasOwnProperty(key)){
    15. copy[key] = cloneDeep(origin[key])
    16. }
    17. }
    18. return copy
    19. }else{
    20. return origin
    21. }
    22. }

    二、计算与类型转换
    1、’+’ 运算
    (1)有一方原始值是字符串,就进行字符串拼接
    如果是引用值,先调用valueOf,如果没有得到原始值,再调用toString,还没得到原始值就报错。
    Array.prototype.toString重写过,将每个元素字符串化后再用逗号拼接到一起

    1. console.log(100 + '10') // => '10010'
    2. console.log('100' + true) // => '100true'
    3. console.log('100' + {valueOf(){return 123},toString(){return '567'}})
    4. // => '100123'
    1. 2)**其余的转换为number类型,再进行计算**
    1. let a = {
    2. valueOf(){
    3. return '123'
    4. },
    5. toString(){
    6. return '678'
    7. }
    8. },
    9. b = {
    10. toString(){
    11. return '123'
    12. }
    13. };
    14. console.log( 100 + a) // => 223
    15. console.log( 100 + a) // => '100123'
    1. 2' - '' * '' / ',都是将变量转化为Number类型<br />Number(null) Number([])都转化为0Number(undefined)返回NaN
    1. console.log( false + [] ) // => 0
    2. console.log( undefined + true ) // => NaN
    3. console.log( null + 0 ) // => 0
    1. 3、计算错题<br />(100得到 NaN
    1. console.log(0/0) // => NaN
    1. 2)自增运算,除了undefined自增后得到NaN,其余js值自增会报错。
    1. true++ // syntaxError
    2. let true_ = 12;
    3. true_++ /consol/ => 13

    三、if语句和逻辑判断语句
    (1)if语句涉及到了boolean值类型的隐式转换
    falsely值有 :’’(空字符串)、undefined、0和NaN、false、null。引用值一般都是truely值(除非原始值操作返回falsely)。
    (2)逻辑语句&& 和 ||
    判断停在哪里,则返回哪个值
    经常用于避免获取后台返回对象的属性产生的错误