zoukankan      html  css  js  c++  java
  • JS中的基本类型和引用类型

    内置类型

    JS 中七种内置类型(null,undefined,boolean,number,string,symbol,object)又分为两大类型

    两大类型:

    • 基本类型: nullundefinedbooleannumberstringsymbol
    • 引用类型Object: Array ,FunctionDate, RegExp

    object.png

    存放位置:

    • 基本数据类型:基本类型值在内存中占据固定大小,直接存储在栈内存中的数据
    • 引用数据类型:引用类型在栈中存储了指针,这个指针指向堆内存中的地址,真实的数据存放在堆内存里。

    obj.png

    值的可变性:

    • 基本数据类型: 值不可变,javascript中的原始值(undefined、null、布尔值、数字和字符串)是不可更改的
    • 引用数据类型:引用类型是可以直接改变其值的
    //基本数据类型
    var str = "abc";
    console.log(str[1]="f");    // f
    console.log(str);           // abc
    
    //引用数据类型
     var a = [1,2,3];
    a[1] = 5;
        console.log(a[1]); // 5
    

    比较:

    • 基本数据类型: 基本类型的比较是值的比较,只要它们的值相等就认为他们是相等的
    • 引用数据类型: 引用数据类型的比较是引用的比较,看其的引用是否指向同一个对象
    //基本数据类型
    var a = 1;
    var b = 1;
    console.log(a === b);//true
    
    //引用数据类型
    var a = [1,2,3];
    var b = [1,2,3];
    console.log(a === b); // false   
    //虽然变量 a 和变量 b 都是表示一个内容为 1,2,3 的数组,
    //但是其在内存中的位置不一样,也就是说变量 a 和变量 b 指向的不是同一个对象,所以他们是不相等的
    

    Typeof

    typeof 对于基本类型,除了 null 都可以显示正确的类型,对于 null 来说,虽然它是基本类型,但是会显示 object,这是一个存在很久了的 Bug, 这与JavaScript的历史有关,null被设计成可以自动转为0

    typeof 1 // 'number'
    typeof '1' // 'string'
    typeof undefined // 'undefined'
    typeof true // 'boolean'
    typeof Symbol() // 'symbol'
    typeof b // b 没有声明,但是还会显示 undefined
    
    typeof null // 'object'
    

    typeof 对于对象,除了函数都会显示 object

    typeof [] 				 // 'object'
    typeof {} 				 // 'object'
    typeof console.log // 'function'
    

    获得一个变量的正确类型,可以通过 Object.prototype.toString.call(xx)。这样我们就可以获得类似 [object Type] 的字符串。

    Object.prototype.toString.call(22)    		//"[object Number]"
    
    Object.prototype.toString.call('22')  		//"[object String]"
    
    Object.prototype.toString.call(null)  		//"[object Null]"
    
    Object.prototype.toString.call(undefined) //"[object Undefined]"
    Object.prototype.toString.call(a)         //"[object Undefined]"
    
    Object.prototype.toString.call(true)      //"[object Boolean]"
    
    Object.prototype.toString.call({a:1})     //"[object Object]"
    

    typeof的安全防范机制
    检查 DEBUG 变量是否已被声明

    if (DEBUG) {
      console.log('Debugging is starting');
    }
    // 报错 ReferenceError 错误
    
    if (typeof DEBUG !== 'undefined') {
      console.log('Debugging is starting');
    }
    

    基本类型

    null

    • Null 类型也只有一个值,就是 null,它的语义表示空值
    • null 是 JavaScript 关键字

    常见问题:null 和 undefined 的区别?
    **
    null表示"没有对象",即该处不应该有值。典型用法是:

    (1) 作为函数的参数,表示该函数的参数不是对象。

    (2) 作为对象原型链的终点。

    Object.getPrototypeOf(Object.prototype)
    // null
    

    undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:

    (1)变量被声明了,但没有赋值时,就等于undefined。
    (2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
    (3)对象没有赋值的属性,该属性的值为undefined。
    (4)函数没有返回值时,默认返回undefined。

    //变量被声明了,但没有赋值时,就等于undefined。
    var i;
    i // undefined 
    
    //调用函数时,应该提供的参数没有提供,该参数等于undefined。
    function f(x){console.log(x)}
    f() // undefined
    
    //对象没有赋值的属性,该属性的值为undefined。
    var  o = new Object();
    o.p // undefined
    
    //函数没有返回值时,默认返回undefined。
    var x = f();
    x // undefined
    

    undefined

    • Undefined 类型表示未定义,它的类型只有一个值,就是 undefined。
    • 任何变量在赋值前是 Undefined 类型、值为 undefined
    • undefined 是一个变量,而并非是一个关键字

    常见问题:为什么有的编程规范要求用 void 0 代替 undefined?
    因为 JavaScript 的代码 undefined 是一个变量,而并非是一个关键字,这是 JavaScript 语言公认的设计失误之一,所以,我们为了避免无意中被篡改,建议使用 void 0 来获取 undefined 值,void 后面随便跟上一个便组成表达式,返回就是 undefined

    let a
    a === undefined  //true
    
    
    a      //undefined
    void 0 //undefined      void 后面随便跟上一个组成表达式返回就是 undefined
    
    a === void 0  //true
    
    

    boolean

    Boolean 类型有两个值, true 和 false

    number

    JavaScript 中的 Number 类型基本符合 IEEE 754-2008 规定的双精度浮点数规则,但是 JavaScript 为了表达几个额外的语言场景(比如不让除以 0 出错,而引入了无穷大的概念),规定了几个例外情况:

    • NaN,占用了 9007199254740990,这原本是符合 IEEE 规则的数字;
    • Infinity,无穷大;
    • -Infinity,负无穷大。

    常见问题:0.1 + 0.2 不是等于 0.3 么?为什么 JavaScript 里不是这样的?
    这里错误的不是结论,而是比较的方法,正确的比较方法是使用 JavaScript 提供的最小精度值:

    console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON);
    

    检查等式左右两边差的绝对值是否小于最小精度,才是正确的比较浮点数的方法。这段代码结果就是 true 了。

    string

    常见问题:字符串有最大长度吗?

    • String 用于表示文本数据。String 有最大长度是 2^53 - 1,这在一般开发中都是够用的,但是有趣的是,这个所谓最大长度,并不完全是你理解中的字符数
    • String 的意义并非“字符串”,而是字符串的 UTF16 编码,我们字符串的操作 charAt、charCodeAt、length 等方法针对的都是 UTF16 编码。所以,字符串的最大长度,实际上是受字符串的编码长度影响的

    symbol

    Symbol 是 ES6 中引入的新类型,它是一切非字符串的对象 key 的集合,在 ES6 规范中,整个对象系统被用 Symbol 重塑。

    //创建
    var mySymbol = Symbol("my symbol");
    

    引用类型

    Object

    Object 表示对象的意思,它是一切有形和无形物体的总称。
    在 JavaScript 中,对象的定义是“属性的集合”。
    属性分为数据属性和访问器属性,二者都是 key-value 结构,key 可以是字符串或者 Symbol 类型

    现象:类型转换

    四则运算符

    • 加法

      • 运算中其中一方为字符串,那么就会把另一方也转换为字符串

      • 如果一方不是字符串或者数字,那么会将它转换为数字或者字符串(具体转换参照对象转原始类型)

    • 其他运算符

      • 只要其中一方是数字,那么另一方就会被转为数字
    1 + '1' // '11'
    true + true // 2
    4 + [1,2,3] // "41,2,3"
    
    4 * '3' // 12
    4 * [] // 0
    4 * [1, 2] // NaN
    

    == 操作符

    JavaScript 中的“ == ”运算,因为试图实现跨类型的比较,它的规则复杂到几乎没人可以记住, 它属于设计失误,并非语言中有价值的部分,很多实践中推荐禁止使用“ ==”,而要求程序员进行显式地类型转换后,用 === 比较

    比较运算符

    1.如果是对象,则转换为原始类型再比较值
    2.如果是字符串,就通过unicode字符索引来比较

    '10'.charCodeAt()  //49
    '厉害'.charCodeAt() //21385
    '10' < '厉害'       //true
    '10' > '厉害'       //false
    

    对象转基本类型

    对象在转换类型的时候,会调用内置的[[ToPrimitive]]函数
    转换流程:

    1. 如果已经是原始类型了,就不需要转换了(因为可以重写Symbol.toPrimitive
    2. 如果需要转换为字符串类型,则直接调用toString方法,转换为基础类型的话就返回转换的值。
    3. 如果不是字符串类型,则先调用valueOf方法,结果不是基础类型的话再调用toString方法
    4. 如果以上处理后,都没有返回原始类型,就会报错

    注意:

    • Symbol.toPrimitive ,有该方法时则只调用该方法,优先级最高
    • 无symbol时  valueOf高于 toString
    let a = {
      valueOf() {
        return 0;
      },
      toString() {
        return '1';
      },
      [Symbol.toPrimitive]() {
        return 2;
      }
    }
    1 + a // => 3
    '1' + a // => '12'
    

    装箱转换

    JS引擎有意去模糊“对象”和“基本类型”之间的关系, 遇到"."时,JS引擎会临时帮我们做一层“装箱转换”,这里就是 new String() 生成一个“临时对象”
    装箱转换,正是把基本类型转换为对应的对象,它是类型转换中一种相当重要的种类

    // Number
    1
    new Number(1)
    
    // String
    'aaa'
    new String('aaa')
    
    // Boolean
    true
    new Boolean(true)
    

    Symbol不能new,我们用特殊的方法把它new出来

    Object(Symbol('aaa'))
    // 或者
    (function(){return this}).call(Symbol('aaa'))
    

    拆箱转换

    JS中拆箱转换是调用了对象的toPrimitive方法来拆箱
    它会依次尝试使用valueOf toString来转换
    如果没有valueOf toString方法,或者这2个方法转换出来的都是非基本类型,则报错


    参考链接:
    https://github.com/amandakelake/blog/issues/34
    https://yuchengkai.cn/docs/frontend/#%E5%AF%B9%E8%B1%A1%E8%BD%AC%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B

    欢迎留言~~~

  • 相关阅读:
    Use Gravatar in ASP.NET
    Silverlight ToolkitPivotViewer
    The Future of Silverlight December 2, 2010 at 9:00
    WPF杂记…
    Windows Phone 7开发者站点
    安装 Internet Explorer 9 Beta 的先决条件
    Internet Explorer 9 Beta(多图)
    Expression Blend4 中文
    Silverlight and WPF Virtual books
    Server2008 安装 Zune
  • 原文地址:https://www.cnblogs.com/zhaoduoduo/p/13444544.html
Copyright © 2011-2022 走看看