1.数据类型

值类型和引用类型

常见的值类型和引用类型

在es6中js的数据类型分为两种:值类型和引用类型
值类型有:Number数值类型、Boolean布尔、String字符串、Undefined未定义、Null空、Symbol
引用类型:Object
其中Object类型包含Function、Array、Date、RegExp、Error
附加小知识:

  1. null和undefined两者值相同,但是类型不相同。null是一种类型,代表空对象;undefined代表一个变量未初始化。
  2. Symbol和BigInt的介绍在文末

值类型和引用类型区别

  1. 存储位置不同,值类型直接存储在栈中,引用类型的值存储在堆中,并把存储地址存储在栈中
  2. 值类型变量赋值时,改变其中一个另外一个不会发生变化
let a = 20 
let b = a 
b = 30 
console.log(a,b)
  1. 引用变量赋值时,只要改变其中一个两个都会发生变化
let a = {
	age = 10 
}
let b = a 
b.age = 20 
console.log(a.age,b.age)

附加深拷贝浅拷贝(面试考点)
浅拷贝:赋值的时候,一个值改变,另外一个也跟着改变是浅拷贝,也就是说将变量所指的引用地址直接赋值给另外一个变量,他们使用的是同一份资源。
手写深拷贝

var obj = {
    "name": "隔壁老王",
    "age": 23,
    "list": {
        "title": "新闻"
    },
    "child": {
        "child": "child"
    },
    "wife": undefined
}
//这里循环引用,引入map就是为了解决循环引用
obj.obj = obj

// 方法一:使用json形式
console.log('test', JSON.parse(JSON.stringify(obj)))

// 方法二
function deepCopy(target, map = new WeakMap()) {
    if (typeof target === 'object') {
        let res = Array.isArray(target) ? [] : {}
        if (map.get(target)) {
            return map.get(target)
        }
        //这里先创建一个空地址
        map.set(target, res)
        for (let key in target) {
            if (target.hasOwnProperty(key) && target[key] != null) {
            	//这里就进行存储值了
                res[key] = deepCopy(target[key], map)
            }
        }
        return res
    } else {
        //这里是出口,如果不是对象类型直接返回
        return target
    }
}
console.log(deepCopy(obj))

Q:为什么要使用弱引用呢?
主要是为了垃圾回收。后期补上
附加一个小知识点:
for…in常用于遍历对象,遍历的是对象的所有属性+对象原型上的所有属性
hasOwnProperty()函数用于判断属性是否是实例对象,结果是一个布尔值,true说明是实例对象,false说明不是实例属性。in操作符会通过对象能够访问给定属性时返回true,无论属性存在实例中还是原型中。
for…of 常用于遍历可迭代对象
不同点时for…in可以操作任何对象,但是for…of必须是带有interator的对象。

总结:以上的代码中考虑了object和array还有null类型

获取数据类型

常见的单词运算符: typeof、void、new、in、instanceof、delete
常用的获取数据类型有:typeof、Object.prototype.toString.call()、instanceof
typeof用来判断变量类型 其返回值为字符串类型,所有的值类型,能够判断引用类型(只能区分object和function)
能够判断的类型有(7种):number、boolean、string、undefined、symbol、object、function

typeof undefined //undefined 
typeof null //object 
typeof 'abc' //string
typeof 123 //number 
typeof [] //object 
typeof {} //object 
typeof true //boolean 
typeof b // b没有明,但是还会显示undefined
typeof Symbol //function 
typeof Symbol(1) //symbol 

更准确的类型判断方法

Object.prototype.toString.call(2) // "[object Number]"
Object.prototype.toString.call('hello') // "[object String]"
Object.prototype.toString.call({hello:'hello'}) // "[object Object]"
Object.prototype.toString.call([2,'hello']) // "[object Array]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(() => {}) // "[object Function]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(Symbol(2)) // "[object Symbol]"

instanceof 方法 可以判断出null不是Object类型

null instanceof Object  //false

判断对象的具体类型,判断实例是否属于某种类型
instanceof的判断规则如何进行的。参考函数/原型链(面试考点)
instanceof实现原理 参考函数/instanceof实现原理(面试考点)

es6新增类型Symbol
是一种新的数据类型,是独一无二的,是一种类似于字符串的数据类型。
主要解决的是命令冲突问题,不能用来做运算。
不能使用for…in遍历,但是可以使用Refect.ownKeys来获取对象的所有键名
创建Symbol

var s = Symbol()
console.log(type s )  //symbol
var s1 = Symbol("wo shi string")  //这个字符串参数就是标识出来这个Symbol干什么的,类似于注释的功能
var  s2 = Symbol("wo shi string")
console.log(s1==s2)   //结果为false
var s3 = Symbol.for('han')     //此时,Symbol是一个对象,通过这种方式创建的Symbol可以通过参数字符串得到唯一的Symbol值
var s4 = Symbol.for('han')
console.log(s3===s4);   //结果为true
可以检测上下文中是否已经存在使用该方法且相同参数创建的 symbol 值,如果存在则返回已经存在的值,如果不存在则新建。
Symbol.keyFor(s4)  //结果为han,这个方法返回一个使用Symbol.for定义的Symbol类型值的key
Symbol.keyFor(s2)   //undefined

使用场景借鉴
1.作为属性名 作为属性名时调用这个属性名


let mySymbol = Symbol()
let obj = {
    //第一种写法,作为属性名称
    [mySymbol]:"helloworld"
}
//第二种写法
obj[mySymbol] = "helloworld"
//第三种写法
Object.defineProperty(obj,mySymbol,{value:"helloworld"})

//获取用Symbol定义的属性名称   以上三种写法的结果都相同
obj[mySymbol]

2.消除魔法字符串


const shapeType = {
    //发现triangle等于哪个值不重要,重要的是不和其他属性名称 冲突就可以
  triangle: Symbol()
};
实现一:
function getArea(shape, options) {
  let area = 0;
  switch (shape) {
    case shapeType.triangle:
      area = .5 * options.width * options.height;
      break;
  }
  return area;
}
实现二:
function getArea(shape ,option){
    let area= 0
    if(shapeType.triangle){
        area = .5 * options.width * options.height;
    }
    return area
}

getArea(shapeType.triangle, { width: 100, height: 100 });

3.属性名遍历

es10新增的BigInt
本来number表示的最大数为2**53-1,现在BigInt可以表示任意大的整数
两个注意点:第一不能使用Math对象进行计算 第二不能是Nunber类型数据直接计算,需要转换后使用
let bignumber = BigInt(12222)
typeof 1n === ‘bigint’; // true
typeof BigInt(‘1’) === ‘bigint’; // true

你可能感兴趣的:(js-基础语法,javascript,前端)