一篇就够-JS数据类型

2020-03-24  本文已影响0人  johe_jianshu

数据类型

根据变量类型传递方式,可以分为基本数据类型和引用数据类型

传参方式

//不影响
var obj = {
    value: 1
};
function foo(o) {
    o = 2;
    console.log(o); //2
}
foo(obj);
console.log(obj.value) // 1
//影响
var obj = {
    value: 1
};
function foo(o) {
    o.value = 2;
    console.log(o.value); //2
}
foo(obj);
console.log(obj.value) // 2

存储空间

基本数据类型存储在内存栈中,引用类型的数据存储在堆中(引用存储在内存栈)


image

类型检测

typeof

  1. 不要用typeof做类型检测
  2. typeof null会错误的返回Object
    • 在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,typeof null 也因此返回 "object"
  3. typeof Function会返回function
  4. typeof 无法区别基本数据类型和引用类型
// 下面的例子令人迷惑,非常危险,没有用处。避免使用它们。
typeof new Boolean(true) === 'object';
typeof new Number(1) === 'object';
typeof new String('abc') === 'object';

类型检测的通用方法

使用Object.prototype.toString()可以获取对象的[[Class]]内部属性。[[Class]]内部属性根据标准,只可能是下面字符串中的一个:
Arguments, Array, Boolean, Date, Error, Function, JSON, Math, Number, Object, RegExp, String.

function isType(obj,type){
    //[object xxx]
    let classProperty = Object.prototype.toString.call(obj).slice(8,-1)
    return classProperty === type
}
//true
is(new String("a"),"String")
//true
is("a","String")

instanceof

object instanceof constructor用来检测一个对象是否为某个构造函数的实例

function A() {
}
function B() {
}
B.prototype = new A()
let b = new B()
b instanceof B // true
b instanceof A // true

instanceof原理:

//判断当前构造函数的prototype是否在原型链上
function new_instance_of(leftVaule, rightVaule) { 
    let rightProto = rightVaule.prototype; // 取右表达式的 prototype 值
    leftVaule = leftVaule.__proto__; // 取左表达式的__proto__值
    while (true) {
        if (leftVaule === null) {
            return false;   
        }
        if (leftVaule === rightProto) {
            return true;    
        } 
        leftVaule = leftVaule.__proto__ 
    }
}

加深原型链理解:


image
function Foo() {
}

//因为Object作为函数则Object.__proto__等于Function.prototype,而Function.prototype是对象,所以Function.prototype.__proto__为Object.prototype
Object instanceof Object // true
Function instanceof Function // true
Function instanceof Object // true
Foo instanceof Foo // false
Foo instanceof Object // true
Foo instanceof Function // true

赋值、浅拷贝和深拷贝

image

赋值和浅拷贝的区别

//对象赋值
var obj = {
    name:'johe',
    age:'18',
    arr:[1,2]
}
var obj2 = obj
obj2.name = 'johe-test'
//受影响
obj.name
//浅拷贝
var obj = {
    name:'johe',
    age:'18',
    arr:[1,2]
}

function shallowCopy(obj){
    var cloneObj = {}
    for(let property in obj){
        // for in 会访问原型链上的属性,所以需要加判断
        if(obj.hasOwnProperty(property)){
            cloneObj[property] = obj[property]
        }
    }
    return cloneObj
}

var obj2 = shallowCopy(obj)
obj2.name="johe-test"
//不受影响,输出johe
obj.name
obj2.arr[1] = 3
//受影响,输出[1,3]
obj.arr

浅拷贝实现方式

var obj = {
    arr:[1,2]
}
var cloneObj = Object.assign({},obj)
cloneObj.arr = [1,3]
//受影响,输出[1,3]
obj.arr
let arr = [1,2,{name:'johe'}]
let arr2 = arr.concat[]
arr2[2].name = "johe-test"
//受影响输出johe-test
arr[2].name

浅拷贝和深拷贝的区别

image

浅拷贝和深拷贝都会返回一个新对象,浅拷贝在拷贝对象属性时,如果是基本数据类型,则拷贝值,如果是引用类型,则拷贝引用(指向同一地址)。
深拷贝在拷贝对象属性时,如果是基本数据类型,则拷贝值,如果是引用类型,则生成新对象递归拷贝。

深拷贝实现

function isType(type,obj){
    return Object.prototype.toString.call(obj).slice(8,-1) === type
}

function deepClone(target){
    let result
    if(isType('Object',target)){
        result = {}
    }else if(isType('Array',target)){
        result = []
    }else{
        return target
    }
    for(let i in target){
        let value = target[i]
        result[i] = deepClone(value)
    }
    return result
}

上一篇 下一篇

猜你喜欢

热点阅读