js数据类型(基本数据类型 | 引用数据类型)

一、数据类型

JS分两种数据类型:

基本数据类型:**Number、String、Boolean、Null、 Undefined、Symbol(ES6),**这些类型可以直接操作保存在变量中的实际值。

引用数据类型Object(在JS中除了基数据类型以外的都是对象,数据是对象,函数是对象,正则表达式是对象)

1、基本数据类型(六种)存放在栈中

基本数据类型是指存放在中的简单数据段,数据大小确定,内存空间大小可以分配,它们是直接按值存放的,所以可以直接按值访问

  • 1、Number数值类型
    Number类型包含整数和浮点数(浮点数数值必须包含一个小数点,且小数点后面至少有一个数字)两种值

注意:在js中浮点数的精度是17位,计算是二进制的计算数 据,所以得到的不是整数

var num1 = 0.1;

var num2 = 0.2;

console.log(num1 + num2);   //0.30000000000000004

NaN:非数字类型,属于数值型基本数据类型

特点:
1):设计任何的NaN操纵都会返回NaN
console.log('ab'/10); // NaN
2) NaN不等于自身。
console.log(NaN == NaN);// false;

判断是否是Number类型

1、isNaN:判断是否是一个非数字类型,传入的非数字类型,返回true,否则返回false
注意:传入的参数首先会被转化为数值,如果参数类型为对象类型,先调用valueOf()方法,再确定该方法返回的值是否可以转换为数值类型,如果不能,再调用toString()方法,再确定返回值
2、typeof
console.log(typeof 12) //Number

数值类型的转换:
Number():可以用于任何的数据类型
parseInt:提取 整数数值
paseFloat:提取浮点数值

  • 2、String 字符串类型

特点:
1、字符串的单引号和双引号作用效果一样
2、字符串有length属性,可以取得字符串的长度
3、字符串的值是不可变的,所以很多的字符串的api不会改变原字符串值

字符串转换:
String():适用于任何的数据类型(null -> null undefined -> undefined)
toString()nullundefined没有这个功能
console.log(null.toString()); //error 报错

  • 3、Boolean 布尔类型
    该类型只有两个值:truefalse
转换为`boolean`:    `Boolean()`
Boolean(undefined):false

Boolean(null):false

Boolean(非空对象包括空数组[]和空对象{}):true

Boolean(0): true || Boolean(0NaN):false

Boolean(非空包括空格字符串):true || Boolean(''):false

[注意]true不一定等于1false也不一定等于0

出现场景:
(1)条件语句导致执行的隐士类转换
(2)字面量或变量定义

类型转换:
Number(true): 1     ||   Number(false) : 0

String(true):'true'      ||   String(false):'false'
  • 4、Null 空对象指针类型
    如果定了一个对象,初始化可以为null,因为null的基本类型是Null,在if语句中默认转化为false,在和数值计算默认为0
    出现场景:对象不存在
类型转换:
Booleam(null)  false

Number(num)  0

String(null)  'null'

Number(null) // 0

  • 5、Undefined
    申明了变量但是没有初始化,默认为undefined,在if语句中默认转化为false,

undefined:表示‘缺少值’,就是应该有一个值,但是没有定义,以下用法是典型的出现undefined情况
(1)变量被申明,等于undefined
(2)调用函数时,应该提供的参数没有提供,该参数等于undefined
(3)对象没有赋值的属性,该属性值为undefined
(4)函数没有返回值,默认返回undefined

类型转换:
Boolean(undefined):  false
 
Number(undefined):  NaN

String(undefined):  'undefined'
  • 6、Symbol
    ES6新增的一个基本数据类型,表示唯一性
 let id1 = Symbol('id');
 let id2 = Symbol('id');
 console.log(id1 == id2);  //false

Symbol属性类型不支持for...inObject.keys()

 let id = Symbol("id");
 let obj = {
  [id]:'symbol'
 };
 for(let option in obj){
     console.log(obj[option]); //空
 }

但是也能有方法去访问:Object.getOwnPropertySymbols
方法会返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。

console.log(Object.getOwnPropertySymbols(obj))
// [ Symbol(c) ]
  • 介绍两个Symbol.forSymbol.keyFor
    (1)、Symbol.for :方法根据给到的键key来运行时的symbol注册表中找到对应的symbol,如果找到了,则返回它,否则新增一个与该键关联的symbol,并放入全局的symbol,这个Symbol值可以是被二次用到的
    返回值:
    返回由给定的 key 找到的 symbol,否则就是返回新创建的 symbol。
Symbol.for("foo"); // 创建一个 symbol 并放入 symbol 注册表中,键为 "foo"
Symbol.for("foo"); // 从 symbol 注册表中读取键为"foo"的 symbol

Symbol.for("bar") === Symbol.for("bar"); // true,证明了上面说的
Symbol("bar") === Symbol("bar"); // false,Symbol() 函数每次都会返回新的一个 symbol

为了防止冲突,最好给你要放入 symbol 注册表中的 symbol 带上键前缀。
Symbol.for("mdn.foo");
Symbol.for("mdn.bar");

(2)、Symbol.keyFor
方法用来获取 symbol 注册表中与某个 symbol 关联的键。

var globalSym = Symbol.for("foo"); 
Symbol.keyFor(globalSym); // "foo"

2、引用数据类型

引用数据类型也叫对象数据类型,包括function,object,array,date,RegExp等可以可以使用new创建的数据,又叫对象类型,他们是存放在(heap)内存中的数据
特点:

  • 引用类型的值可以改变
  • 引用数据类型可以添加属性和方法
  • 引用数据类型的赋值是对象引用
  • 引用类型的比较是引用的比较
  • 引用类型是同时保存在栈区中和堆区中的,引用类型的存储需要在内存的栈区和堆区中共同完成,栈区保存变量标识符和指向堆内存的地址

注意:在引用类型赋值时对象的引用,所以从一个变量向另一个变量赋值引用类型的值时,同样会将存在在变量中的对象的值赋值一份到新的变量分配的空间,引用类型保存在变量中的时对象在堆存在的地址,所以与基本数据类型的简单赋值不同,这个值的副本实际上时一个指针,而这个指针指向储存在堆内存的一个对象,那么赋值操作后,两个变量都保存了同一个对象的地址,而这个地址都指向同一个对象,因此改变其中任何一个变量,都会影响
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jbmIM5T9-1596703084649)(images/screenshot_1595230430200.png)]

在ECMAScript中,Object类型是所有它的实例的基础

Object的每个实例都具有下列的属性和方法:

  • constructor:构造函数
  • hasOwnProperty(proertyName)
    用于检查给定的属性在当前对象实例(而不是实例的原型)中是否存在。
  • isPropertyOf(Object)
    用于检查其原型链的对象是否存在于指定对象的实例中,是则返回true,否则返回false。
var a = {} function Person() {} 

var p1 = new Person() // 继承自原来的原型,但现在已经无法访问  

var Person.prototype = a var p2 = new Person() // 继承a  

console.log(a.isPrototypeOf(p1)) // false a是不是p1的原型 

 console.log(a.isPrototypeOf(p2)) // true a是不是p2的原型  

console.log(Object.prototype.isPrototypeOf(p1)) // true  

console.log(Object.prototype.isPrototypeOf(p2)) // true

  • propertyIsEnumerable(propertyName)
    用于检查给定的属性是否可以用 for-in 语句进行枚举。
  • toLocaleString()
    返回对象的字符串表示,该字符串与执行环境的地区对应。
  • toString()
    返回对象的字符串表示。
  • valueOf()
    返回对象的字符串、数值、布尔值表示。通常与toString()方法的返回值相同。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ncTTVVzi-1596703084652)(images/screenshot_1595228465109.png)]

拓展:声明对象的几种方式

 <script>
//内置函数
        var obj1=new Object();
        obj1.name="zhuyu";
        obj1.age=21;
        obj1.uni=function(){
            console.log(this.name+this.age);
        }
        console.log(obj1);
        obj1.uni();
 
//字面量
        var obj2={
            name:"zhuyu2",
            age:21,
            uni2:function(){
                console.log(this.name+this.age)
            }
        }
        console.log(obj2);
        obj2.uni2();
 
 
// 自定义函数
        function Obj(name,age){
            this.name=name;
            this.age=age;
            this.uni3=function(){
                console.log(this.name+this.age)
            }
        }
        var obj3=new Obj("zhuyu3",21);
        console.log(obj3);
        obj3.uni3();
 
// Es6类
 
        class Obj2{
            constructor(name,age){
                this.name=name;
                this.age=age;
            }
            uni4(){
        console.log(this.name+this.age)
            }
        }
        var obj4=new Obj2("zhuyu4",21);
        console.log(obj4);
        obj4.uni4();
 
//使用Object.create()
 
        var person={
            image:"true",
            uni5:function(){
                console.log(`名字是${this.name},年龄是${this.age}`);
            }
        }
       var obj5=Object.create(person);
       obj5.name="zhuyu5";
       obj5.age=21;
       obj5.image=false;
       obj5.uni5();
       console.log(obj5)
    </script>

3、基本数据类型和引用数据类型的区别

总结基本数据类型和引用数据类型区别

1、声明变量时内存分配不同

*原始类型:在栈中,因为占据空间是固定的,可以将他们存在较小的内存中-栈中,这样便于迅速查询变量的值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MXBAdxMe-1596703084654)(images/screenshot_1595226759783.png)]

*引用类型:存在堆中,栈中存储的变量,只是用来查找堆中的引用地址。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UsfodwlF-1596703084656)(images/screenshot_1595226765978.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1467GOxa-1596703084658)(images/screenshot_1595227087417.png)]

这是因为:引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响

2、不同的内存分配带来不同的访问机制

在javascript中是不允许直接访问保存在堆内存中的对象的,所以在访问一个对象时,首先得到的是这个对象在堆内存中的地址,然后再按照这个地址去获得这个对象中的值,这就是传说中的按引用访问。而原始类型的值则是可以直接访问到的。

3、复制变量时的不同

1)原始值:在将一个保存着原始值的变量复制给另一个变量时,会将原始值的副本赋值给新变量,此后这两个变量是完全独立的,他们只是拥有相同的value而已。

2)引用值:在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量,也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的改变都会反映在另一个身上。(这里要理解的一点就是,复制对象时并不会在堆内存中新生成一个一模一样的对象,只是多了一个保存指向这个对象指针的变量罢了)。多了一个指针
浅拷贝:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SoeUg10W-1596703084659)(images/screenshot_1595226833036.png)]

深拷贝:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JxsVP0Bi-1596703084660)(images/screenshot_1595226846817.png)]

4、参数传递的不同(把实参复制给形参的过程

首先我们应该明确一点:ECMAScript中所有函数的参数都是按值来传递的。

但是为什么涉及到原始类型与引用类型的值时仍然有区别呢?还不就是因为内存分配时的差别。

1)原始值:只是把变量里的值传递给参数,之后参数和这个变量互不影响。

2)引用值:对象变量它里面的值是这个对象在堆内存中的内存地址,这一点你要时刻铭记在心!

因此它传递的值也就是这个内存地址,这也就是为什么函数内部对这个参数的修改会体现在外部的原因了,因为它们都指向同一个对象。

4、检测类型

  • 法一:typeof

最基本的判断方式,该操作符返回一个表示数据类型的字符串,numberstringbooleanobjectfunctionundefinedsymbol

  1. ‘undefined’ --未定义的变量或值

  2. ‘boolean’ --布尔类型的变量或值

  3. ‘string’ --字符串类型的变量或值

  4. ‘number’ --数字类型的变量或值

  5. ‘object’ --对象类型的变量或值,或者null(这个是js历史遗留问题,将null作为object类型处理)

  6. ‘function’ --函数类型的变量或值

     console.log(typeof a);    //'undefined'

    console.log(typeof(true));  //'boolean'

    console.log(typeof '123');  //'string'

    console.log(typeof 123);   //'number'

    console.log(typeof NaN);   //'number'

    console.log(typeof null);  //'object'    

    var obj = new String();

    console.log(typeof(obj));    //'object'

    var  fn = function(){};

    console.log(typeof(fn));  //'function'

    console.log(typeof(class c{}));  //'function'
  • 法二:instanceof

运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性
语法:object instanceof constructor
(1)基础类型

let num = 1
num instanceof Number // false

num = new Number(1)
num instanceof Number // true

这两个都是一样的数值,为什么不一样?
因为instanceof 检测的是:检测目标的__proto__与构造函数prototype,相同返回true,不同返回false,对于stringboolean是一样的
注意:

new String(1) // String {"1"}
String(1) // "1"

(2) 继承关系的用法

// 判断 foo 是否是 Foo 类的实例 , 并且是否是其父类型的实例
 function Aoo(){}
 function Foo(){}
 Foo.prototype = new Aoo();//JavaScript 原型继承

 var foo = new Foo();
 console.log(foo instanceof Foo)//true
 console.log(foo instanceof Aoo)//true

(3) 复杂类型

let arr = []
arr instanceof Array // true
arr instanceof Object // true
Array.isArray(arr) // true

注意:
(new Number(1)) instanceof Object // true
(4) 其他类型

let reg = new RegExp(//)
reg instanceof RegExp // true
reg instanceof Object // true

let date = new Date()
date instanceof Date // true
date instanceof Object // true

但是Fuction不一样

function A() {}
let a = new A()
a instanceof Function // false
a instanceof Object // true
A instanceof Function // true

–>分析a为什么不是?

  • a是new出来,所以是经过构造,因此已经是对象,不再是函数,所以false。
  • a是经过构造的对象,返回ture没问题。
  • 如上所述,A是个函数,因此没什么概念上的问题。但是要知道A.__proto__Function.prototypeƒ () { [native code] },这是与object以后处于原型链上层的存在,而且与object平级:
let obj = {}
obj.__proto__ // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
obj.__proto__.prototype // undefined

let A = function() {}
A.__proto__ // ƒ () { [native code] }
A.__proto__.prototype // undefined

本章内容图谱:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qZLYd9tI-1596703084662)(images/screenshot_1595231058140.png)]

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值