zoukankan      html  css  js  c++  java
  • 【重学前端】JS基础-变量和类型

    变量和类型

    • 1.JavaScript规定了几种语言类型

      1.Undefined
      2.Null(js中的数据在底层是以二进制存储,如果前三位为0,那么就会判定为object,而null的所有都为0)
      3.Boolean
      4.String
      5.Number
      6.Symbol(ECMAScript 6 新定义,实例是唯一且不可改变的)
      7.Object
      
    • 2.JavaScript对象的底层数据结构是什么

      
      
    • 3.Symbol类型在实际开发中的应用、可手动实现一个简单的Symbol

      • 应用场景1:使用Symbol来作为对象属性名(key)

        const PROP_NAME = Symbol();
        const PROP_AGE = Symbol();
        
        let obj = {
        	[PROP_NAME]: "一斤代码"
        }
        obj[PROP_AGE] = 18;
        
        console.log(obj[PROP_NAME]); // '一斤代码'
        console.log(obj[PROP_AGE]); // 18
        

        【注意】Symbol类型的key是不能通过Object.keys()或者for...in来枚举的,利用该特性,我们可以把一些不需要对外操作和访问的属性使用Symbol来定义。实现当使用JSON.stringify()将对象转换成JSON字符串的时候,Symbol属性也会被排除在输出内容之外。

        获取以Symbol方式定义的对象属性
        // 使用Object的API
        Object.getOwnPropertySymbols(obj); // [Symbol(name)]
        
        // 使用新增的反射API
        Reflect.ownKeys(obj); // [Symbol(name), 'age', 'title']
        
      • 应用场景2:使用Symbol来替代常量

        //由于定义const变量的时候需要立即赋值,这样定义,直接就保证了三个常量的值是唯一的了
        const TYPE_AUDIO = Symbol();
        const TYPE_VIDEO = Symbol();
        const TYPE_IMAGE = Symbol();
        
      • 应用场景3:使用Symbol定义类的私有属性/方法

        利用Symbol的唯一性以及模块化机制,实现类的私有属性和方法。

        //a.js
        const PASSWORD = Symbol()
        
        class Login {
          constructor(username, password) {
            this.username = username
            this[PASSWORD] = password
          }
        
          checkPassword(pwd) {
              return this[PASSWORD] === pwd
          }
        }
        export default Login
        
        //b.js
        import Login from './a'
        
        const login = new Login('admin', '123456')
        login.checkPassword('123456')  // true
        login.PASSWORD  // oh!no!
        login[PASSWORD] // oh!no!
        login["PASSWORD"] // oh!no!
        
    • 4.JavaScript中的变量在内存中的具体存储形式

      JavaScript中的变量分为基本类型和引用类型

      • 基本类型是保存在栈内存中的简单数据段,它们的值都有固定的大小,保存在栈空间,通过按值访问

      • 引用类型是保存在堆内存中的对象,值大小不固定,栈内存中存放的该对象的访问地址指向堆内存中的对象,JavaScript不允许直接访问堆内存中的位置,因此操作对象时,实际操作对象的引用。

      • //例子:
        let a1 = 0; // 栈内存
        let a2 = "this is string" // 栈内存
        let a3 = null; // 栈内存
        let b = { x: 10 }; // 变量b存在于栈中,{ x: 10 }作为对象存在于堆中
        let c = [1, 2, 3]; // 变量c存在于栈中,[1, 2, 3]作为对象存在于堆中
        

      复制行为

      • 在栈内存中的数据发生复制行为时,系统会自动为新的变量分配一个新值,最后这些变量都是相互独立互不影响的
      • 引用类型的复制,为新的变量分配相同的地址指针,保存在栈内存中,该地址指针在堆内存中访问到的具体对象实际上是同一个,因此一改变数值,双方都改。

      生存期

      • 当一个方法执行时,会建立自己的栈内存,在方法内定义的变量都会放入这块栈内存里,方法执行结束后,这个内存栈也将自然销毁。
      • 堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(方法的参数传递时很常见)。只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。
    • 5.基本类型对应的内置对象,以及他们之间的装箱拆箱操作

      • 内置对象

        • 数据封装类对象:Object、Array、Boolean、Number 、String

        • 其他对象:Function、Math、Date、RegExp、Error

          • Error6种错误类型(前4个较常见)

             1.SyntaxError: 语法错误
             2.ReferenceError: 引用错误 要用的东西没找到
             3.RangeError: 范围错误  专指参数超范围
             4.TypeError: 类型错误  错误的调用了对象的方法
             5.EvalError: eval()方法错误的使用
             6.URIError: url地址错误
            
      • 特殊的基本包装类型(Boolean、Number 、String)

        • 包装类型:专门封装原始类型的数据,并提供对数据常用操作的内置对象方法。

        • 生存期:只要用原始类型的数据调用方法或者访问属性时,js引擎都会自动创建对应的包装类型。对象方法调用完,包装类型对象会自动释放。

        • 无法直接给基本类型添加属性和方法,但可以在基本包装类型对象的原型下面添加,因为每个对象都有原型。

        • 装箱(把基本数据类型转化为对应的引用数据类型的操作)

          • 隐式装箱

            let a = 'sun';
            let b = a.indexof('s');
            // 上面代码在后台实际的步骤为:
            let a = new String('sun')
            let b = a.indexof('s')
            a = null
            
          • 显式装箱

            let a = new String('sun	');
            let b = a.indexof('s')
            
        • 拆箱(把引用类型转化为对应基本数据类型的操作)

          let name = new String('sun')
          let age = new Number(24)
          console.log(typeof name) // object
          console.log(typeof age) //  object
          // 拆箱操作(通常通过引用类型的valueof()和toString()方法实现)
          console.log(typeof age.valueOf()); // number // 24  基本的数字类型
          console.log(typeof name.valueOf()); // string  // 'sun' 基本的字符类型
          console.log(typeof age.toString()); // string  // '24' 基本的字符类型
          console.log(typeof name.toString()); // string  // 'sun' 基本的字符类型
          
    • 6.理解值类型和引用类型

      • 值类型,即基本类型

        • string、number、boolean、undefined、null、symbol

        • 1、占用空间固定,保存在栈中
          2、保存与复制的是值本身
          3、使用typeof检测数据的类型
          4、基本类型数据是值类型
          
      • 引用类型

        • Object、Array、Function

        • 1、占用空间不固定,保存在堆中
          2、保存与复制的是指向对象的一个指针
          3、使用instanceof检测数据类型
          4、使用new()方法构造出的对象是引用型
          
    • 7.null和undefined的区别

      • 用法不同

        null表示 “没有对象”,即该处不应该有值。
        (1)作为函数的参数,表示该函数的参数不是对象。
        (2)作为对象原型链的终点。
        
        undefined表示“缺少值”,就是此处应该有一个值,但是还没有定义。
        (1)变量被声明了,但没有赋值时,就等于undefined。
        (2)调用函数时,应该提供的参数没有提供,该参数就等于undefined。
        (3)对象没有赋值的属性,该属性的值为undefined。
        (4)函数没有返回值时,默认返回undefined。
        
      • 类型转换

        Number(undefined)  // NaN
        Number(undefined + 10)  //NaN
        Number(null)  // 0
        Number(10 + null)  // 10
        
      • 数据类型

        undefined === null  //false   undefined与object
        undefined == null  //true  js规定
        
    • 8.至少可以说出三种判断JavaScript数据类型的方式,以及他们的优缺点,如何准确的判断数组类型

      • typeof

        • 优点:使用简单,能判断出所有基本数据类型+object(null是object)+function

        • 缺点:不能区分object类型的具体类型,比如 Array 、Date 以及自定义类。

        • var arr = [];
          console.log(typeof arr);//object
          
      • instanceof

        • 优点:能判断出引用类型

        • 缺点:只能判断出用对象定义的基本数据类型;不能跨iframe

        • var arr = [];
          alert(arr instanceof Array);//true
          
      • constructor

        • 优点: 基本能检测所有的类型(除了null和undefined,并且会报错。因为null和undefined是无效的对象,因此是不会有constructor存在的)

        • 缺点:constructor易被修改导致判断出错,也不能跨iframe

        • var arr = [];
          alert(arr.constructor == Array);//true
          
      • Object.prototype.toString.call( ) ;

        • 优点:能判断出所有的类型

        • 缺点:IE6下,undefined和null均为Object

        • var arr = [];
          console.log(Object.prototype.toString.call(arr));//[object Array]
          
    • 9.可能发生隐式类型转换的场景以及转换原则,应如何避免或巧妙应用

      • 应用场景

      • 场景一:算术运算符

        • 字符串+数字=字符串数字

          console.log(10+"abc");//10abc
          
        • 非字符串+数字=转数字+数字

          console.log(10+true);//11
          
        • -*/% 将字符转换成数字,再进行正常的运算,结果必为数值,若字符不是纯数字,则结果为NaN

        • (+字符串)转数字

      • 场景二:关系(比较)运算符

        • <<=>>=!===

          • 任意一边出现数值,就会把另一边转成数值,再进行比较。

            console.log([1] == 1);//true,相当于1 == 1
            console.log([] == true);//false,相当于0 == 1
            console.log({} > true);//false,相当于 NaN > 1
            console.log('true' <= 0);//false,相当于NaN <= 0
            
          • 一个值转换为另一个值并不意味着两个值相等

            console.log(new Date() == 'Fri Jul 15 2016 22:12:05 GMT+0800 (中国标准时间)');//true
            
            console.log(Number(null));//0
            console.log(null == 0);//false
            
            console.log(Boolean(NaN));//false
            console.log(NaN == false);//false,NaN与任何值都不等,包括自己
            
          • 两边是对象

            console.log({} == {});//false
            console.log([] == []);//false
            
          • 两边都是字符串,则是按照字符串的按位比较法。

      • 场景三:isNaN()

        • 参数转成数值,严格转换,能识别小数点
      • 场景四:判断语句if()

        • 隐式转换,将其他转成布尔值
      • 场景五:逻辑运算符

        • 逻辑非 !
          • 隐式转换,将其他数据类型转成布尔值
          • 优先级高于关系运算符
        • 位运算符(&、|、^、&&、||)
          • 隐式转换,将其他数据类型转成数字
          • 优先级低于关系运算符
        • 位运算符(<<等)
          • 隐式转换,将其他数据类型转成数字
          • 优先级高于关系运算符
      • 避免隐式转换

        • 如果两遍的值中有 true 或者 false , 千万不要使用 == (会被转为数字0,1来进行判断,会出现一些意外的情况)
        • 如果两遍的值中有[]、''或者0,尽量不要使用 ==
        • 使用全等===来代替==
      • 巧妙应用

        使用一个对象,进行隐式类型转换
        const a = (function() {
            let i = 1;
            return {
                valueOf: function() {
                    return i++;
                }
            }
        })();
        
        console.log(a == 1 && a == 2 && a == 3); // true
        
    • 10.出现小数精度丢失的原因,JavaScript可以存储的最大数字、最大安全数字,JavaScript处理大数字的方法、避免精度丢失的方法

      • 小数精度丢失的原因:计算机的二进制实现和位数限制有些数无法有限表示。

      • JS的基础类型Number,遵循 IEEE 754 规范,采用双精度存储(double precision),占用 64 bit。符号位(1bit),指数(11bit),尾数(52bit),因此 JS 中能精准表示的最大整数是 Math.pow(2, 53)-1,十进制即 9007199254740991。

      • 最大安全数字

        console.log(Number.MAX_SAFE_INTEGER); //9007199254740991
        console.log(Number.MIN_SAFE_INTEGER); //-9007199254740991
        
      • JS 处理大数字的方法

        • json-bigint
        • bignumber.js:原理是把所有数字当作字符串,重新实现了计算逻辑,缺点是性能比原生的差很多。
        • proposal bigint
        • 大数运算:化为字符串再运算
      • 避免精度丢失的方法

        • 小数:小数化整进行运算再化为小数。
        • CalcEval.js引擎

    本文作者:AlubNoBug

    本文链接:https://www.cnblogs.com/AlubNoBug/p/13911382.html

  • 相关阅读:
    直面焦虑烦恼 谈谈成长
    Makefile入门1
    递归
    极客时间的专栏
    作者介绍
    1.试除法判定质数 2.分解质因数 质数
    17.没有上司的舞会 树形DP
    17.二分图的最大匹配
    16.染色法判定二分图
    15.Kruskal算法求最小生成树
  • 原文地址:https://www.cnblogs.com/AlubNoBug/p/13911382.html
Copyright © 2011-2022 走看看