美文网首页
一篇就够-JS数据类型

一篇就够-JS数据类型

作者: johe_jianshu | 来源:发表于2020-03-24 19:11 被阅读0次

数据类型

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

  • 基本数据类型:Number、Boolean、String、Undefined、Null、Symbol(es6)
    • Null表示空对象指针
    • Undefined表示未定义
  • 引用类型:Object是所有引用类型的父对象
    • Object、Function、Arguments、Date、Math、Error、RegExp、自定义对象等

传参方式

  • 基本数据类型和引用类型都是按值传递
  • 按值传递,传递的是变量里的内容,不管盒子里面存的是基本类型值还是引用类型的地址
//不影响
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
  • 可以知道prototype是构造函数独有属性,proto是任意对象都有的(不管当前对象是作为构造函数还是原型,)并且指向其构造函数的prototype,constructor的是原型独有的属性
  • Function对象是任意构造函数的构造函数(包括function Object),所以任意构造函数的proto指向Function.prototype
  • 任意对象最终继承自Object.prototype(最终proto指向Object.prototype),Object.prototype.proto按规定是null
  • Function的prototype和proto都指向Function.prototype
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

浅拷贝实现方式

  • Object.assign:把任意多个源对象的可枚举属性拷贝给目标对象,然后返回目标对象。当被拷贝对象只有一层(一层全是基本数据类型)时,是深拷贝
var obj = {
    arr:[1,2]
}
var cloneObj = Object.assign({},obj)
cloneObj.arr = [1,3]
//受影响,输出[1,3]
obj.arr
  • Array.prototype.concat()
let arr = [1,2,{name:'johe'}]
let arr2 = arr.concat[]
arr2[2].name = "johe-test"
//受影响输出johe-test
arr[2].name
  • Array.prototype.slice()

浅拷贝和深拷贝的区别

image

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

深拷贝实现

  • JSON.parse(JSON.stringify()):最常用的深拷贝方法,但不能处理函数和正则
  • 手写递归方法:
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
}

相关文章

  • 一篇就够-JS数据类型

    数据类型 根据变量类型传递方式,可以分为基本数据类型和引用数据类型 基本数据类型:Number、Boolean、S...

  • 一篇就够-JS的new实现

    new的作用 可以看到,经过new之后返回了一个对象,该对象的构造函数原型为Fruit.prototype,也就是...

  • JS里的数据类型转换

    上一篇文章(JS里的数据类型)介绍了js中的数据类型。这篇主要介绍数据类型转换。 一、任意类型转字符串 转换成st...

  • JS 里的数据类型转换

    前言:上一篇博客讲到JS里的数据类型,相信大家已经了解到7种数据类型,那么这章将详细深入了解JS的不同数据类型之间...

  • JS 里的数据类型(下)

    上一篇博客介绍了JS中的简单数据类型,这篇博客主要介绍JS中的复杂数据类型——对象(object)。 1. 概述 ...

  • js中的数据类型

    js中的数据类型分6种 1;string 字符串型; 2;Number;数字型; 在js中数据类型就...

  • JavaScript基础知识点整理(下)

    在上一篇文章《JS基础知识点(一)》中我们学习了什么是js、js写法、js数据类型、js的函数。在本篇文章中我们将...

  • JS的类型转换

    JS的数据类型: 首先, JS的数据类型分为基本数据类型和引用数据类型基本数据类型: string number ...

  • js对象数组的深拷贝方法以及其他方法

    js判断数据类型是否为对象 js判断数据类型是否为数组

  • 2022前端面试题汇总(附答案)更新中

    JS相关 1.JS中的数据类型 (1)数据类型分为基本数据类型和引用数据类型基本数据类型:number、null、...

网友评论

      本文标题:一篇就够-JS数据类型

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