zoukankan      html  css  js  c++  java
  • 2021 路漫漫其修远兮,吾将上下而求索

    2021-01-02

    JS的数据类型

    基本数据类型(原始值类型)

    •   number
      • NaN 
      • Infinity 
    •   string
    •   boolean
    •   null
    •   undefined
    •   symbol
      • 可以做为对象的属性(属性的类型不是传统的String了)
      • 创建唯一值的
    •   bigint

    引用数据类型(对象类型)

    •   object
      • 普通对象
      • 数组对象
      • 正则对象
      • 日期对象
      • Math数学函数对象
    •   function

    数据类型检测(js中有且只有四种)

    • typeof  检测数据类型的逻辑运算符
    • instanceof 检测是否为某个类的实例
    • constructor 检测构造函数
    • Object.prototype.toString.call 检测数据类型
    /*
     * 数据类型检测 
     *   typeof 返回字符串
     *      typeof null ->"object"
     *      typeof 实现CALL的对象「函数、箭头函数、生成器函数、构造函数」 ->"function"
     *      typeof 剩下未实现CALL的对象 ->"object"
     *   
     *   ECMAScript提供的内置类型在计算机底层都是按照二进制数据存储的
     *      以对应的数字开始代表不同的类型 
     *      1:数字   010:浮点数
     *      100:字符串
     *      110:布尔
     *      -2^30:undefined
     *      000000:null
     *      000:对象
     *    设计上的缺陷
     */
    // console.log(typeof typeof []); //->”string“
    
    // 数据类型转换
    // 对象转换为数字/字符串「字符串拼接、数学运算、特殊方法处理、==比较(隐式转换、显式转换)...」
    //  + 首先检测对象的 Symbol.toPrimitive 这个属性,获取其原始值
    //  + 如果没有这个属性,则继续调用它的valueOf,也是获取原始值
    //  + 如果值不是原始值,则继续调用toString转换为字符串
    //  + 再把字符串基于Number转换为数字
    
    /* let obj = {
        name: 'xxx'
    };
    console.log(obj - 10); //数学运算:先把obj隐式转换为数字,再进行运算 */
    /* 
    let obj = {
        name: 'xxx',
        [Symbol.toPrimitive](hint) {
            // hint检测到浏览器隐式规定的转换类型:'number'/'string'/'default'
            return 10;
        }
    };
    console.log(obj - 10); */

    详解typeof

    •  返回的结果都是字符串(引申:alter方法返回的结果也是字符串)
    • 局限性:
      • typeof null => "object"  是一个bug因为所有的值在内存中都是按照二进制存储的,typeof检测时认为前几位都是000的是object而null的前几位正好是000,但其实null是一个基本数据类型
      • typeof 不能细分对象类型(检测普通对象或数组对象等都是"object")

    let a=typeof typeof typeof[12,23];
    console.log(a);  //"string"
    /*
    typeof [12,23] => "object"
    typeof "object" => "string"
    */

    详解number:NaN/isNaN/Infinity/parseInt/Number()

    数字类型:

    • 普通数字
    • NaN not a number  NaN!=NaN 
    • Infinity,-Infinity
    let res=parseFloat('left:200px');
    if(res===200){
     alter(200);
    }else if(res ===NaN){
     alrer(NaN)
    }else if(typeof res==='number'){
     alter('number')
    }else{
     alter('Invalid Number')
    }

     把其他数据类型转化为数字的方法:

    • 强转换(利用底层机制转换) Number([value])
      • 一些隐式转换都是基于Number完成的
        • isNaN('12px')先把其他类型值转为数字再检测
        • 数学运算 '12px'-13
        • 字符串==数字  两个等于号比较多时候也是要把其他值转为数字
        • ...
    • 弱转换(基于一些额外的方法)parseInt([value])  parseFloat([value])
    //parseInt处理的值是字符串,从字符串左侧开始查找有效数字字符(遇到非有效数字字符停止查找)->如果处理的值不是字符串,需要先转化为字符串然后开始查找
    //Number 直接调用浏览器最底层的数据类型检测机制完成
    //Number中 true 1 false 0
    //Number中 null 0  undifined NaN 空字符串0
    //Number中 字符串中必须保证都是有效数字才会转化成数字,否则都是NaN
    // 0 NaN null undefined 空字符串转为布尔都为假
    parseInt("") //NaN
    Number("") //0
    isNaN("") //隐式转换先把“”转完数字(Number) isNaN(0) false
    parseInt(null) //NaN
    Number(null) //0
    isNaN(null)  //false
    parseInt("12px) //12
    Number("12px") //NaN
    isNaN("12px") //true
    parseFloat("1.6px")+parseInt("1.2px")+typeof parseInt(null) //2.6number
    isNaN(Number(!!Number(parseInt("0.8")))) //true
    typeof !parseInt(null)+!isNaN(null)//booleantrue

    let result =10 +false +undefined+[]+'tencent'+null+true+{};
    console.lof(result)
    //10+0=>10
    //10+NaN=>NaN
    //NaN+[]=>NaN+""=>"NaN"
    //"NaNtencentnulltrue[object Object]

     Number({})=>Number("[object Object]")=>NaN  

    Number([])=>Number("")=>0 

      ({}).toString()它调用Object上的toString

      ([]).toString()  它调用Array上的toString

    ==号的一些比较规则:

    规律:

    1.对象=字符串 对象转为字符串

    2.null==undefined 但是和其他值不相等

    3.剩下两边都不同都转为数字

    //对象==布尔   都转为数字再比较
    []==true 
    //number([]) =>number("")=>0
    0==1
    false

    2021-01-06

    数据类型转换规则及Symbol.toPrimitive

    18.2.5 parseInt (string , radix) 
    20.1 Number Objects

    let result = 100 + true + 21.2 + null + undefined + "Tencent" + [] + null + 9 + false;
    console.log(result);
    var a = ?;
    if (a == 1 && a == 2 && a == 3) {
    console.log('OK');
    }
    let arr = [27.2,0,'0013','14px',123];
    arr = arr.map(parseInt);
    console.log(arr);
    JS运行机制:堆(Heap)/栈(Stack)/上下文(EC)/全局对象(GO)/变量对象(VO/AO)
    var a = 12;
    var b = a;
    b = 13;
    console.log(a);
     
    -----------------
     
    var a = {n: 12};
    var b = a;
    b['n'] = 13;
    console.log(a.n);
     
    -----------------
     
    var a = {n: 12};
    var b = a;
    b = {n: 13};
    console.log(a.n);
    var a = {n: 1};
    var b = a;
    a.x = a = {n: 2};
    console.log(a.x);
    console.log(b);
    var x = [12, 23];
    function fn(y) {
    y[0] = 100;
    y = [100];
    y[1] = 200;
    console.log(y);
    }
    fn(x);
    console.log(x);
    /*
     * 对象转换为数字或者字符串
     *   1.查找对象的 Symbol.toPrimitive 
     *   2.对象.valueOf()  原始值:numberstringoolean
    ullundefinedsymboligint
     *   3.对象.toString() 变为字符串
     *   4.字符串转换数字 Number(str)
     * 
     * ==相等  ===绝对相等
     *   ==在比较的时候,如果两边类型不一致,则转换为相同的数据类型
     *     NaN==NaN  false    Object.is(NaN,NaN)->true
     *     null==undefined -> true    null===undefined -> false   null&undefined和其他任何值比较都是不相等的
     *     对象==字符串   对象转换为字符串
     *     剩余的情况都是转换为数字
     * 
     *   ===类型不一致,不会转换,直接false
     */
    
    // 第一类:隐式进行数据类型转换的时候进行处理的
    /* var a = {
        i: 0
    };
    // valueOf / toString
    a[Symbol.toPrimitive] = function () {
        // this->a
        return ++this.i;
    };
    // a[Symbol.toPrimitive]()
    if (a == 1 && a == 2 && a == 3) {
        console.log('OK');
    } */
    
    /* var a = {
        i: 0,
        [Symbol.toPrimitive]() {
            return ++this.i;
        }
    };
    if (a == 1 && a == 2 && a == 3) {
        console.log('OK');
    } */
    
    /* var a = [1, 2, 3];
    // a.shift() ->1
    a.toString = a.shift;
    if (a == 1 && a == 2 && a == 3) {
        console.log('OK');
    } */
    
    // 第二类:ES6 数据劫持 
    /* let obj = {};
    Object.defineProperty(obj, 'name', {
        // 以后当我们操作对象的name属性的时候(获取或者设置),触发getter/setter
        get() {
            return '逗你玩';
        },
        set(value) {
            console.log(value);
        }
    }); */
    
    /* // var a = 12; //全局上下文中,基于var/function声明变量,也相当于给window设置了属性 window.a=12
    var i = 0;
    Object.defineProperty(window, 'a', {
        get() {
            return ++i;
        }
    });
    if (a == 1 && a == 2 && a == 3) {
        console.log('OK');
    } */
    
    //============JS中的数据类型转换
    /*
     * 把其它的数据类型转换为number类型 
     *    例如:==比较、数学运算(+不仅仅是数学运算,还有字符串拼接)...
     * 
     * 显式转换方案:
     *    Number([val]) -> 隐式转换一般调取的都是这个方法  「浏览器有自己的特殊处理,针对于每一种情况都有详细的规则」
     *    parsetInt/parseFloat([val])
     *       parsetInt([val],[radix])处理机制
     *         [val] 必须是一个字符串,如果不是,则也要默认转换为字符串
     *         [radix]不设置(或者写的是零):正常都是按照10处理的,如果字符串是以”0x“开始的,默认值是16...
     *       先在[val]中,找到所有符合[radix]进制的内容(从左到右查找,直到遇到不符合的为止「不论后面是否还有符合进制的,都不在查找了」),然后再把找到的内容看做[radix]进制,转换为十进制
     *       [radix]范围  2~36,除了0以外(0->10/16),不在这个范围内,结果都是NaN
     */
    // parseInt('12px') ->  parseInt('12px',10) -> 在字符串中找到所有符合10进制的内容 ‘12’ -> 最后把'12'当做看做10进制,转换为10进制 -> 12
    // parseInt('12px',1) -> NaN
    // console.log(parseInt(null)); //->parseInt('null',10) -> NaN  
    
    // 把其它进制转换为10进制?
    // '10101'  2机制 -> 10进制
    // 1*2^0 + 0*2^1 + 1*2^2 + 0*2^3 + 1*2^4
    // 4^-1 -> 1/4    4^-3 -> 1/(4^3)
    
    
    // 把一个函数作为值传递给另外一个函数执行(实参):回调函数
    // parseInt(27.2,0) 
    //    parseInt('27.2') -> 27
    // parseInt(0,1)
    //    NaN
    // parseInt('0013',2)
    //    '001' 看做2进制 转换为10进制
    //    1*2^0 -> 1
    // parseInt('14px',3)
    //    '1' 看做3进制 转换为10进制
    //    1*3^0 -> 1
    // parseInt(123,4)
    //    parseInt('123',4)
    //    '123' 看做4进制 转换为10进制
    //    3*4^0 + 2*4^1 + 1*4^2 -> 3+8+16 -> 27
    /* let arr = [27.2, 0, '0013', '14px', 123];
    arr = arr.map(parseInt);
    console.log(arr); */
    
    // 数据中有多少项,就迭代多少次,每一次执行回调函数(item当前迭代项 index索引),支持回调函数返回值,返回啥就把当前项替换成啥,原始数组不变,以新数组返回!!
    /* let arrNew = arr.map(function (item, index) {
        return '@';
    }); */
    
    /*
     * 把其它数据类型转换为布尔:
     *   只有”0/NaN/null/undefined/空字符串“ 转换为false,其余都是true
     *   例如:
     *     if(1){} 
     *     ! 取反
     *     !! 转换为布尔
     *     ...
     */
    
    
    /*
     * ”+“还存在字符串拼接 
     *   +两边都有值,有一边出现字符串或者对象,则为字符拼接
     *     特殊:{}+10 -> 10  {}看做代码块(ES6 块级上下文),真正运算的只有 +10 ->10
     *          ({}+10) -> '[object Object]10'
     *   +只有一边或者++x再或者x++,都是数学运算
     *     +'10' -> 10
     *     10+(++x) -> 先把x累加1,然后和10运算
     *     10+(x++) -> 先拿x的值和10运算,最后再x累加1
     *     
     *     x++ !== (x+=1 == x=x+1)
     */
    /* let result = 100 + true + 21.2 + null + undefined + "Tencent" + [] + null + 9 + false;
    console.log(result); */
    
    // 10+{} -> "10[object Object]"  原本是想把{}变为数字,但是Symbol.toPrimitive/valueOf/toString,调到toString变为字符串,此时符合了有一边变为字符串了,则是字符串拼接
    
    /* let x = '10';
    console.log(++x); //->11
    
    x = '10';
    x += 1; //->x=x+1
    console.log(x); //->'101' */
    
    //=======================
    /*
     * JS运行的环境:
     *   + 浏览器
     *   + webview  WebApp(Hybride混合APP) 
     *   + node.js
     *   + ...
     * 
     * 浏览器能够运行JS代码,是因为提供了代码运行的环境:栈内存(Stack)
     *   + 栈内存也是从计算机的内存分配出来的一块内存
     *   + 执行环境栈 E(execution)C(context)Stack
     *   
     * 执行代码的过程中,为了区分是在哪个环境下执行(全局/函数/块...),首先会产生一个执行上下文:EC
     *   + EC(G) 全局上下文,全局代码在这执行
     *   + EC(X) 某个函数的执行上下文
     */
    
    /* var a = 12;
    var b = a;
    b = 13;
    console.log(a); */
    
    
    /* var a = {
        n: 12
    }; //a -> 0x0001
    var b = a;
    b = {
        n: 13
    }; //b -> 0x0002
    console.log(a.n); //=>12 */
    
    
    // 课后思考:
    var a = {
        n: 1
    };
    var b = a;
    a.x = a = {
        n: 2
    };
    console.log(a.x);
    console.log(b);
    // a.x 成员访问,优先级20「优先计算的」
    //  a.x=a=?  先处理a.x=?
    //  a=a.x=?  先处理a.x=?
    
    /* var a = 12,
        b = 12;
    // var a=12;  var b=12; */
    
    /* var a = b = 12;
    // var a;  b没有var
    // 1.创建值12
    // 2.连等操作是按照从右到左
    //    b -> 12
    //    a -> 12 */
    
    // https://developer.mozilla.org/zh-CN/docs/web/javascript/reference/operators/operator_precedence

     

  • 相关阅读:
    iOS开发常见错误(转)
    SVN各种错误提示产生原因及处理方法大全(转)
    SVN常见问题(转)
    iPhone6 Plus、iPhone6、iPhone5S和之前版本真实分辨率
    各类 HTTP 返回状态代码详解(转)
    js:全局作用域和调整浏览器窗口大小
    python之制作模块
    python之模块time | strftime || 模块datetime | timedelta | 计算3天前的日期
    python之模块 sys | os
    python之正则表达式 | match | split | findall | sub替换 |
  • 原文地址:https://www.cnblogs.com/kangxinzhi/p/14224129.html
Copyright © 2011-2022 走看看