js数据类型

81 阅读6分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情 >>

昨夜西风凋碧树。独上高楼,望尽天涯路。

基本类型

  • 空值(null)
  • 未定义(undefined)
  • 布尔值(boolean)
  • 数字(number)
  • 字符串(string)
  • 符号(symbol,ES6中新增)

空值(null)和未定义(undefined)

typeof null  // object
typeof undefined // undefined

typeof

根据二进制判断,所以 typeof null 被判断成了对象

  • 000:对象

  • 1:整数

  • 010:浮点数

  • 100:字符串

  • 110:布尔

有 2 个值比较特殊:

  • undefined:用 - (−2^30)表示。

  • null:对应机器码的 NULL 指针,一般是全零。

    if (JSVAL_IS_VOID(v)) {  // (1)
        type = JSTYPE_VOID;
    } else if (JSVAL_IS_OBJECT(v)) {  // (2)
        obj = JSVAL_TO_OBJECT(v);
        if (obj &&
            (ops = obj->map->ops,
                ops == &js_ObjectOps
                ? (clasp = OBJ_GET_CLASS(cx, obj),
                clasp->call || clasp == &js_FunctionClass) // (3,4)
                : ops->call != 0)) {  // (3)
            type = JSTYPE_FUNCTION;
        } else {
            type = JSTYPE_OBJECT;
        }
    } else if (JSVAL_IS_NUMBER(v)) {
        type = JSTYPE_NUMBER;
    } else if (JSVAL_IS_STRING(v)) {
        type = JSTYPE_STRING;
    } else if (JSVAL_IS_BOOLEAN(v)) {
        type = JSTYPE_BOOLEAN;
    }
    

    注释(1):判断是否为 undefined

    注释(2):如果不是 undefined,判断是否为对象

    注释(3):判断值是否有对象的标志位。如果它是可调用的,或者说通过内部属性[[Class]]可以表明它是一个函数。否者它就是一个对象

    这样一来,null 就出了一个 bug。根据 type tags 信息,低位是 000,因此 null 被判断成了一个对象。这就是为什么 typeof null 的返回值是 object。

instanceOf

instanceof 是通过原型判断是否是同一类型

   function _instanceof(l, r) {
       var o = r.prototype;
       l = l.__proto__;
       while (true) {
           if (l === null) {
               return false;
           }
           if (o === l) {
               return true;
           }
           l = l.__proto__;
       }
   }

number

JavaScript 能够准确表示的整数范围在-2^532^53之间(不含两个端点),超过这个范围,无法精确表示这个整数

基本类型的封装类型

字符串布尔类型都有方法,是因为使用对应的变量时,编译器会将其装箱成对应的对象类型,例如 var s = 'test',如果使用s变量时会将s = new String(s)进行封装,一旦属性引用结束,这个新创建的对象就会被销毁。

var s = 'test';
s == new String(s)  // true
s.len = 4
s.len   // undefined

隐士类型转换

  • 字符串和数字之间相等的比较

    字符串和数字之间相等的比较

    '42' == 42 // true Number('42') == 42
    
  • 其他类型和Boolean类型值比较

    Boolean 类型转换成number

    '42' == true  // false   '42' == Number(true)1
    
  • Null 与 undefined

    Null == undefined   // true
    
  • NaN

    NaN == NaN false    NaN !=NaN true
    
  • 对象与非对象的比较

    通过ToPrimative(Obj) 获取对象的字符串值或者数值

    42 == [42] // true
    
    • ToNumber
    > 为了将值转换为基本数据类型,抽象操作ToPrimitive会先检查该值是否有valueof()方法,没有然后在检查是否有通toString()方法
    
     ```javascript
     var a = { 
         valueOf:function(){ return '23' },
         toString:function(){ return '12' } 
     }
    
     Number(a) // 23
     a == 23 // true
    
     var a = { 
         toString:function(){ return '12' } 
     }
    
     Number(a) // 12
     
     
     ```
    
    • JSON.stringify(会发生强制toString()类型转换

      • 字符串、数字、布尔值和null的转换规则和ToString一致
      • 如果传递给JSON.stringify的对象中定义了toJSON方法,那么该方法会在字符串化前调用,以便将对象转化成安全的JSON值
      var a ={ 
          name:'wky',
          age:10,
          toJSON:function(){ 
              return this.name
          } 
      }
      JSON.stringify(a) ;// ""wky""
      

symbol

1. Symbol 是基本数据类型

Symbol 是基础数据类型之一 typeof Symbol() 返回symbol

2. Symbol 不支持构造函数方式

new Symbol() 会报错

3. Symbol 使用方法

Symbol 会生成一个唯一的标识(不会重复)

var symbol1 = Symbol('aa');
var symbol2 = Symbol('bb');
symbol1 == symbol2  // 输出 false
4. Symbol 函数 for 和 keyFor

for函数生成唯一的Symbol数据, keyFor返回Symbol数据类型的key值

    Symbol.for('eeee'); // Symbol(eeee)
    Symbol.keyFor(Symbol.for('eee')) // 返回eee
5. 具体使用场景
var obj11 ={
    name:'zhangsan'
}
var obj21 = {
    name:'李四'
}

var obj31 = Object.assign(obj11, obj21);
console.log(obj31);
// 其中一个名字被融合没了

// 具体使用场景
var obj1 ={
    [Symbol('name')]:'zhangsan'
}
var obj2 = {
    [Symbol('name')]:'李四'
}

var obj3 = Object.assign(obj1, obj2);

console.log(obj3,'obj3');
//  不会被融合

6.模拟实现Symbol类型

 (function(){  
    var getOVFnName = (function(){
        let index = 0;
        return function(desc) {
            index = index +1;
            return index + '-' + desc;
        }
    })();
    
    function SymbolPolify (desc){

        var symbol = Object.create({
            toString(){
                return this.__name__
            } 
        })
        Object.defineProperty(symbol, '__name__', {
            value: getOVFnName(desc)
        });
        return symbol;
    }
    
    var d = SymbolPolify('dddd');
    var a = SymbolPolify('aaaaa');
    console.log(d, 'd');
    console.log(a, 'a');

})()

引用类型

  • Array
  • Object
  • Function
  • Date
  • Regx

Array

  1. sort

方法默认是按''排序 如果数据里是数组,也会将数字转换成字符串进行排序

扩展知识  V8 sort 排序: 数据量少的时候是用插入排序算法,数据量大的时候是用的快排算法

2. 操作方法

  • concat
     var list1 = [1, 3, 4];
     var concatList = list1.concat([4, 5, 6]).concat([[8, 9, 10]]);
     // 返回数组
     console.log(concatList); [1,3,4,4,5,6,[8,9,10]]

  • slice 数组截取方法
    • 返回截取后的数组 startIndex endIndex endIndex不包含
    • 如果endIndex 为负数,则截取的是 倒数第几个数 当然也不包含endIndex的索引值
  const sliceList = concatList.slice(0, 4);
  console.log(sliceList);   [1,3,4,4]
  • splice 方法 删除 插入 替换 返回删除的数组 ,如果没有删除,则返回一个空数组

    • 删除 startIndex deleteItems (从哪里开始删除,删除多少项数据)

    • 插入 startIndex, deleteItems, insertObj (从哪里开始插入,0,要插入的数据)

    • 替换 startIndex, deleteItems, repleaceObjs(从哪里开始替换,替换几项,替换的项)

  1. 位置方法
  • indexOf 从数组的开头开始查找
  • lastIndexOf 从数组的结尾开始查找
     接收两个参数: value, index : 要查找的value值和查找起点位置的索引 , value值是=== 才会返回
     // indexOf
     const index = concatList.indexOf('4'); concatList.indexOf(4);   
     console.log(index);  // -1    2 

     const lastIndex = concatList.lastIndexOf(4)
     console.log(lastIndex);  // 4

  1. 迭代方法

    • every
    • filter
    • forEach
    • map
    • some
        params: function(value, index, array), this
    
  2. 归并方法

    • reduce 从数组的开头开始归并
    • reduceRight 从数组的结尾开始归并
        params: function(result, nextValue, index, array),  initValue(数组为空时必须付初始值,不然会报错)
        var reduceList = [];
    
        var sum = reduceList.reduce((val, nextVal) => {
            return val + nextVal;
        }, 0)   // 必须给最初的初始值
        console.log(sum);  // 0
    

Object Es6中新增的方法

  1. set 不会给对象中新增属性
var setObj1 = {
     names:[],
     set name (x){
         return this.names.push(x);
     },
    //  get name (){
    //      return this.names
    //  }
 }

 console.log( setObj1.name ) // undefined set不会新增属性信息
  1. Object.freeze 冻结对象

被冻结的对象不能修改属性值,也不能删除属性,也不能修改属性的可读写性可枚举性等信息

var setObj1 = {
     names:[],
     age: 20,
     set name (x){
         return this.names.push(x);
     },
     get name (){
         return this.names
     }
 }
 setObj1.name = 'nihao';
 console.log(setObj1.name, setObj1.names);



 var freezeO  = Object.freeze(setObj1);
 freezeO.names= [];

 console.log(freezeO === setObj1);

 freezeO.age = 30;

 console.log(freezeO);   // {names:[nihao], age: 20}  不能修改信息值 不会改变

  1. Object.seal

密封一个对象 可以修改属性值 但是不能删除或者新增属性

Function

function 和 arguments

  • 函数形参和实参 在函数体中存在一个形参的引用,指向当前传入的实参列表,通过它可以获得参数的值
  • 函数体内this指向 在严格模式中this 指向 undefined
  • arguments 是指向实参对象的引用
  • arguments中的数组 与形参是别名的关系
  • 严格模式下 arguments是个保留字,并且不能被重新赋值
  • 非严格模式下 arguments是个标识符, 能被修改
var a = 5;
function test(a){
    a = 10
    console.log(a, 'inner'); // 10
}
test();
console.log(a, 'wrap') // 5

function testArguments(b){
  arguments[0] = 20;
  console.log(b, 'inner arguments') // 20
}
testArguments(a);
console.log(a, 'wrap arguments') // 5

var list = [];
function testArray(list){
    list.push(10);
    console.log(list,'inner'); // [10]
}
testArray(list);
console.log(list, 'wrap'); // [10]

Date(后续补充)

Regx(后续补充)