美文网首页
JavaScript 变量和类型篇

JavaScript 变量和类型篇

作者: 阿羡吖 | 来源:发表于2020-04-21 17:57 被阅读0次

    一、JavaScript基础

    变量和类型

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

    JavaScript中的每一个值都有他自己的类型,JavaScript规定了七种语言类型:
    1.Undefined 未定义
    2.Null 空,只有一个值,就是null表示空值
    3.Boolean true&false
    4.String 字符串
    5.Number 数字
    6.Symbol 独一无二的值(ES6新定义)
    7.Object 对象

    • 2.JavaScript对象的底层数据结构是什么

    es5自带的:array、object
    es6自带的:set map、weakset weakmap(强引用、弱引用,Set和Map 数据结构)
    简单的说,object 就是哈希表,array 是在 object 的基础上继续封装而实现的,至于 map 和 set,则是在 array 的基础上又继续封装而实现的。至于线程安全,这个是说不准的,即使 js 没有多线程,协程和异步都会导致线程不安全。

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

    1.使用Symbol来作为对象属性名(key)

    1. 使用Symbol来代替常量
    2. 使用Symbol定义类的私有属性/方法
      具体可参考:https://www.jianshu.com/p/f40a77bbd74e
    const name = Symbol()
    const age = Symbol()
    let obj ={
      [name]:"一堆代码"
    }
    obj[age] = 28
    
    obj[name] //'一堆代码'
    obj[age] // 28
    
    • 4.JavaScript中的变量在内存中的具体存储形式

    JavaScript中的变量分别为基本类型和引用类型
    基本类型:保存在栈内存中的简单数据段、值都是有固定大小、保存在栈空间,通过按值访问
    引用类型:保存在堆内存中的对象,值大小不固定,栈内存中存放的该对象的访问地址指向堆内存中的对象,JavaScript不允许直接访问堆内存中的 位置,因此操作对象时,实际操作对象的引用

    结合代码与图解

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

    当我们要访问堆内存中的引用数据类型时
    1.从栈中获取该对象的地址引用
    2.再从堆内存中取得我们需要的数据

    基本类型发生赋值行为

    let a = 20;
    let b = a;
    b =30;
    console.log(b,a) //30 20
    
    image.png
    在栈内存中的数据中发生赋值行为时,系统会自动为新的变量分配一个新值,最后这些变量都是相互独立互不影响的

    引用类型发生赋值行为

    let a = { x: 10, y: 20 }
    let b = a;
    b.x = 5;
    console.log(a.x); // 5
    

    1.引用类型的赋值,同样为新的变量b分配一个新的值,保存在栈内存中,不同的是,这个值仅仅是引用类型的一个指针
    2.他们指向同一个值,也就是地址指针相同,在堆内存中访问到的具体对象实际上是同一个
    3.因为b.x发生改变,a.x也发生改变 这就是引用类型的特性

    image.png
    • 5.基本类型对应的内置对象,以及他们之间的装箱拆箱操作

    1.装箱:
    把基础数据类型转换为对应的引用类型的操作称为装箱。

    var s1 = "some text"
    var s2 = "s1.substring(2)"
    

    如上,变量s1是一个基本类型值,它不是对象,所以不应该有方法。但js内部为我们完成了一系列处理(即装箱)使他能够调用方法,实现机制如下:

    1.创建String类型的一个实例
    2.在实例上调用指定的方法
    3.销毁这个实例

    var s1  = new String("some text");
    var s2 = s1.substring(2);
    s1 = null
    console.log(s2) // me text
    

    2.拆箱:
    把引用类型转换为基础类型称为拆箱。
    通过引用类型的valueOf()或者toString()方法来实现。

    var objNum = new Number(123);  
    var objStr =new String("123");  
    
    console.log( typeof objNum ); //object
    console.log( typeof objStr ); //object
    
    console.log( typeof objNum.valueOf() ); //number
    console.log( typeof objStr.valueOf() ); //string
    console.log( typeof objNum.toString() ); // string 
    console.log( typeof objStr.toString() ); // string
    
    • 7.null和undefined的区别
    console.log(null==undefined);    //true  因为两者都默认转换成了false
    console.log(typeof undefined);    //"undefined"  
    console.log(typeof null);       //"object"  
    console.log(null===undefined);    //false   "==="表示绝对相等,null和undefined类型是不一样的,所以输出“false”
    

    null 表示没有对象,即此处不应该有值

    1.作为函数的参数,表示该函数的参数不是对象
    2.作为对象原型链的终点

    undefined表示缺少值,即此处应该值,但没有定义

    1.定义了型参,没有实参,显示undefined
    2.对象属性名不存在时,显示undefined
    3.函数没有写返回值,即没有写return,拿到的是undefined
    4.写了return,当没有赋值 拿到的是undefined

    null 默认转成0
    undefined 默认转成 NaN

    • 8.至少可以说出三种判断JavaScript数据类型的方式,以及他们的优缺点,如何准确的判断数组类型

    1.typeof
    typeof返回一个表示数据类型的字符串,返回结果包括:number boolean string object undefined function
    typeof可以对js基础数据类型做出准确的判断,在对于引用类型返回的基本上都是object。判断是引用类型,typeof使用起来比较不方便。
    2.instanceof
    instanceof 是用来判断是否为B的实例,表达式为:A instanceof B,如果A是B的实例,则返回true,反之,返回false *isntanceof 检测的是原型
    3.Object.prototype.toString
    toString是Object原型对象上的一个方法,该方法默认返回其调用者的具体类型,严格讲,是toString运行时this指向的对象类型,返回的类型格式为[object,xxx],xxx是具体的数据类型,其中包括:String,Number,Boolean,Undefined,Null,Function,Date,Array,RegExp,Error,HTMLDocument,… 基本上所有对象的类型都可以通过这个方法获取到。
    4.constructor 查看对象对应的构造函数
    constructor在对应对象的原型下面,是自动生成的,当我们写了一个构造函数的时候,程序会自动添加,构造函数名为:prototype.comstructor = 构造函数名
    优缺点

    image.png
    • 9.可能发生隐式类型转换的场景以及转换原则,应如何避免或巧妙应用
    可能发生隐式类型转换的场景以及转换原则:
    转数字 转字符串 转布尔值
    undefined NaN “undefined” false
    null 0 “null” false
    true 1 “true”
    false 0 “false”
    0 “0” false
    -0 "0" false
    NaN “NaN” false
    Infinity “Infinity” true
    -Infinity “-Infinity” true
    1(非零) “1” true
    {}(任意对象) 见下文 见下文 true
    9 9 “9” true
    ”a” NaN 使用.join()方法 true
    function(){}(任意函数) NaN 见下文 true

    1.运算符的转换:-,*,/,%,会将操作数转为数字去计算,但+不一样,两边纯数字会按数字相加,纯字符串会拼接,但数字与字符串也会拼接。

    console.log(1 - '2'); //-1
    console.log(1 * '2'); //2
    

    2.双等号的隐式转换:
    1).双等号两边只要有一边是NaN 便会返回false 且自身不相等

    console.log(NaN == 1); //false
    console.log(NaN == NaN);//false
    console.log(undefined == NaN);//false
    

    2).布尔值会转换为数字,false转换为0,true转换为1

    console.log(0 == false); //true
    console.log(1 == true); // true
    

    3).对象转换

    var a = [];
    var b = [];
    var c = {};
    var d = {};
    console.log("[] == []");
    console.log(a == b); // false
    console.log(a == c); // false
    console.log(d == c); // false
    console.log(a == !b); // true
    

    解析:对于前三个的原理是一样的,当两个值都是对象 (引用值) 时, 比较的是两个引用值在内存中是否是同一个对象. 因为此 [] 非彼 [], 虽然同为空数组, 确是两个互不相关的空数组, 所以为false。
    而最后一个是因为右边空数组会转化为true,取反变为false,false变为0;左边空数组变为空字符串再变为0,0==0就为true。

    如何避免或巧妙应用

    把字符串类型转换为数字


    image.png
    • 10.出现小数精度丢失的原因,JavaScript可以存储的最大数字、最大安全数字,JavaScript处理大数字的方法、避免精度丢失的方法
    出现小数精度丢失的原因
    0.1 + 0.2 != 0.3 // true
    

    计算机的二进制实现和位数限制有些数无法有限表示。此时只能模仿十进制进行四舍五入了,但是二进制只有 0 和 1 两个,于是变为 0 舍 1 入。这即是计算机中部分浮点数运算时出现误差,丢失精度的根本原因。

    JavaScript可以存储的最大数字、最大安全数字

    js的number类型有最大值(安全值)。即2的53次方,为9007199254740992。如果超过这个值,那么js会出现不精确的问题。这个值为16位。

    JavaScript处理大数字的方法、避免精度丢失的方法

    对于整数,前端出现问题的几率可能比较低,毕竟很少有业务需要需要用到超大整数,只要运算结果不超过 Math.pow(2, 53) 就不会丢失精度。
    对于小数,前端出现问题的几率还是很多的,尤其在一些电商网站涉及到金额等数据。解决方式:把小数放大倍数(乘倍数),再缩小回原来倍数(除倍数)

    相关文章

      网友评论

          本文标题:JavaScript 变量和类型篇

          本文链接:https://www.haomeiwen.com/subject/cutuihtx.html