博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js变量及类型
阅读量:5350 次
发布时间:2019-06-15

本文共 9804 字,大约阅读时间需要 32 分钟。

js变量及类型

编写时间:2019-07-15

更新时间:2019-7-26 8:45

作者:鬼小妞

目的:本文旨在介绍

  • ,
  • JS内存(待更新)

备注: 本文整理及编写了与js变量及类型相关的一些知识,仅供参考,描述不当的地方,请评论指正

状态:待更新~2019-7-26

[TOC]

1. JS的数据类型

最新的ECMAScript标准规定了8种数据类型,其把这8种数据类型又分为两种:原始类型和对象类型。

1.1 原始类型

  • Null:只包含一个值:null

  • Undefined:只包含一个值:undefined

  • Boolean:包含两个值:true和false

  • Number:整数或浮点数,还有一些特殊值(-Infinity、+Infinity、NaN)

  • BigInt: 大于等于2^53的所有数字

  • String:一串表示文本值的字符序列

  • Symbol:一种实例是唯一且不可改变的数据类型

(在es10中加入了第七种原始类型BigInt,现已被最新Chrome支持)

在JavaScript中,Number 可以准确表达的最大数字是2^53-1,大于等于2^53的所有数字可以使用BigInt表达。

在ECMAScript标准中,它们被定义为primitive values,即原始值,代表值本身是不可被改变的。

1.2 对象类型(引用类型)

  • 对象类型(引用类型):除了常用的Object,Array、Function等都属于特殊的对象
    • "标准的" 对象, 和函数
    • 日期:Date
    • 有序集: 数组Array和类型数组
    • 键控集: Maps, Sets, WeakMaps, WeakSets
    • 结构化数据: JSON
    • 标准库中更多的对象请查看

根据上面的对象类型(引用类型)列举的具体有以下常见的几种 对象类型(引用类型)有这几种:

  • object、
  • Array、
  • RegExp、
  • Date、
  • Function、
  • 特殊的基本类型包装对象(String、Number、Boolean)
  • 单体内置对象(Global、Math)

1.2.1 请区分对象类型、普通对象、函数对象

(1). 对象类型

  • 对象类型是包含基本对象,而基本对象包括一般对象、函数对象和错误对象。

  • Object 、Function 是 JS 自带的函数对象 (请查看)。

所以 ,你会发现,在使用typeof 运算符查询变量的类型时,结果可能值参考里会出现function,例如:

console.log(typeof Object); //function console.log(typeof Function); //function  复制代码

得到的都是function,即函数对象

如何区分一般对象和函数对象 凡是通过 new Function() 创建的对象都是函数对象,其他的都是一般对象(一般对象包括数组[]、日期、标准对象{})

使用typeof,如果输出值是

  • function——————函数对象
  • object————————一般对象

(2). 标准对象

基本对象包括一般对象、函数对象和错误对象。 这里的一般对象包括数组、日期、标准对象等, 凡是通过 new Function() 创建的对象都是函数对象,其他的都是一般对象(一般对象包括数组[]、日期、标准对象{}); 标准对象就是我们创建的{},标准对象 是通过new Object()创建的,比如如下方式创建的:

1. var o1 = {}; 2. var o2 =new Object();3. var o3 = new f1();复制代码

01和03归根结底都是通过new Object()生成的,我们可以根据typeof来验证,如果输出object,那就表明是一般对象(一般对象包括数组[]、日期、标准对象{})。

console.log(typeof o1); //object console.log(typeof o2); //object console.log(typeof o3); //object复制代码

(3). 函数对象

基本对象包括一般对象、函数对象和错误对象。 凡是通过 new Function() 创建的对象都是函数对象,其他的都是一般对象(一般对象包括数组[]、日期、标准对象{}); 函数对象是通过new Function()创建的,比如如下方式创建的:

1. function f1(){}; 2. var f2 = function(){};3. var f3 = new Function('str','console.log(str)');复制代码

f1和f2归根结底都是通过New Function()生成的,我们可以根据typeof来验证,如果输出object,那就表明是一般对象(一般对象包括数组[]、日期、标准对象{})

console.log(typeof f1); //function console.log(typeof f2); //function console.log(typeof f3); //function   复制代码

1.2.2 如何区分数组[]和标准对象{}

  • 数组Array:是可索引的集合对象,根据new Array()创建来的

  • 标准对象Object:是基本对象,根据new Object()创建来的

我们都知道一般对象包括数组、日期、标准对象。 所以使用typeof校验出的结果为object的是一般对象(一般对象包括数组[]、日期、标准对象{}), 请看以下输出:

console.log(typeof {});//objectconsole.log(typeof []);//object复制代码

  • {}是根据new Object()创建的,

  • []是根据new Array()创建的,但原型链上有Object.prototype


而通过new来创建的,不是funtion(函数对象)就是object(一般对象,一般对象包括数组[]、日期、标准对象{})

console.log(typeof new Function());//functionconsole.log(typeof new Object());//objectconsole.log(typeof new Array());//object复制代码

所以,怎么区分数组[]和标准对象{},请点击查看下文

1.2.3 为什么对象类型又被称为引用类型

对象类型也称引用类型,为什么对象类型又被称为引用类型?

相对于具有不可变性的原始类型,我习惯把对象称为引用类型,引用类型的值实际存储在堆内存中,它在栈中只存储了一个固定长度的地址,这个地址指向堆内存中的值。

引用类型:当复制保存着对象的某个变量时,操作的是对象的引用,但在为对象添加属性时,操作的是实际的对象。引用类型值指那些可能为多个值构成的对象。

2. 基本类型和(对象类型)引用类型的区别

  1. 基本类型的变量是存放在栈区的(栈区指内存里的栈内存);
  2. 引用类型的值是同时保存在栈内存和堆内存中的对象;
  3. 基本类型的比较是值的比较;
  4. 引用类型的比较是引用的比较;
  5. 引用类型包括某些特殊的基本类型包装对象(String、Number、Boolean)
  6. 引用类型是有方法和属性的,但基本类型是没有的

3. JavaScript 中的基本类型包装对象

除了 null 和 undefined之外,所有基本类型都有其对应的包装对象:

  • String: 为字符串基本类型。
  • Number: 为数值基本类型。
  • Boolean :为布尔基本类型。
  • Symbol :为字面量基本类型。

这个包裹对象的方法返回基本类型值。

我们回过头来对比引用类型(对象类型)和基本类型,你发现了什么:

基本类型:String、Number、Boolean、Null、Undefined、BigInt、Symbol

引用类型:String、Number、Boolean、Object、Array、Date、Function、Error、RegExp、Math、Globle。

you get!! 2者都有String、Number、Boolean,但是:

  • 基本类型是没有属性和方法的,这三个基本类型String、Number、Boolean都有自己对应的包装对象。
  • 引用类型(对象类型)的String、Number、Boolean是表示特殊的基本类型包装对象(String、Number、Boolean),包装对象呢,其实就是对象,有相应的属性和方法。

所以,我们以前肯定见过这样的代码:

var s1 = 'hello world'; //string 基本类型var s2 = new String('hello world'); //object 字符串对象 console.log(s1.charAt(0));// hconsole.log(s2.charAt(0));// h console.log(typeof s1);//stringconsole.log(typeof s2);//object复制代码

str 虽然是基本类型,但是它却有方法,怎么来的呢?

var s1 = 'hello world';  s1.charAt(0)调用方法,后台会执行以下操作:复制代码
  1. 基本类型找到对应的包装对象类型,然后通过包装对象创建出一个和基本类型值相同的对象s1;

  2. 然后这个对象s1就可以调用包装对象下的方法,并且返回

  3. 销毁这个临时创建的对象, s1 =null;

例1:

var str = 'hello'; //string 基本类型var s2 = str.charAt(0); //在执行到这一句的时候 后台会自动完成以下动作 :    【          var str = new String('hello'); // 1 找到对应的包装对象类型,然后通过包装对象创建出一个和基本类型值相同的对象         var s2 = str.chaAt(0); // 2 然后这个对象就可以调用包装对象下的方法,并且返回结给s2.         str = null;  //    3 之后这个临时创建的对象就被销毁了, str =null;      】  alert(s2);//h alert(str);//hello     注意这是一瞬间的动作 实际上我们没有改变字符串本身的值。就是做了下面的动作.这也是为什么每个字符串具有的方法并没有改变字符串本身的原因。复制代码

实际上我们没有改变字符串本身的值。就是做了下面的动作.这也是为什么每个字符串具有的方法并没有改变字符串本身的原因。

面试题1

var str = 'hello';str.number = 10; //假设我们想给字符串添加一个属性number ,后台会有如下步骤    【         var str = new String('hello'); // 1 找到对应的包装对象类型,然后通过包装对象创建出一个和基本类型值相同的对象         str.number = 10; // 2 通过这个对象调用包装对象下的方法 但结果并没有被任何东西保存         str =null; // 3 这个对象又被销毁     】 alert(str.number); //undefined  当执行到这一句的时候,因为基本类型本来没有属性,后台又会重新重复上面的步骤    【         var str = new String('hello'); // 1 找到基本包装对象,然后又新开辟一个内存,创建一个值为hello对象         str.number = undefined   // 2 因为包装对象下面没有number这个属性,所以又会重新添加,因为没有值,所以值是未定 ;然后弹出结果         str =null; // 3 这个对象又被销毁     】 复制代码

所以,基本类型无法直接添加属性和方法,那么我们怎么才能给基本类型添加方法或者属性呢?

答案是在基本包装对象的原型下面添加,即使销毁了这个对象,但是原型对象上的属性和方法还是保存了下来,后面调用的时候,就可以在它的原型对象上重新获取这些方法。每个对象都有原型。请看

面试题2

//给字符串添加方法  要写到对应的包装对象的原型下才行var str = 'hello';String.prototype.number= 10str.number; // 5 执行到这一句,后台依然会偷偷的干这些事    【        var str = new String('hello');// 找到基本包装对象,new一个和字符串值相同的对象,        str.number;  // 通过这个对象找到了包装对象下的属性并调用         str =null; //  这个对象被销毁     】复制代码

如何添加方法:

//给字符串添加方法  要写到对应的包装对象的原型下才行var str = 'hello';String.prototype.last= fuction(){     return this.charAt(this.length);}; str.last(); // 5 执行到这一句,后台依然会偷偷的干这些事    【         var str = new String('hello');// 找到基本包装对象,new一个和字符串值相同的对象,        str.last();  // 通过这个对象找到了包装对象下的方法并调用         str =null; //  这个对象被销毁        】复制代码

4. 使用typeof 运算符查询变量的类型

如何查询判断变量的类型? 使用typeof 运算符查询变量的类型

下表总结了可能的返回值。有关类型和原始值的更多信息,可查看 页面。

类型 结果
Undefined "undefined"
Null "object"
Boolean "boolean"
Number "number"
String "string"
函数对象([[Call]] 在ECMA-262条款中实现了) "function"
Symbol(ECMAScript 6 新增) "symbol"
任何其他对象 "object"
宿主对象(由JS环境提供) Implementation-dependent

注意:typeof是无法分辨标准对象{}和数组对象[]的, 因为:


  • {}是根据new Object()创建的,

  • []是根据new Array()创建的,但原型链上有Object.prototype


而通过new来创建的,不是funtion(函数对象)就是object(一般对象,一般对象包括数组[]、日期、标准对象{})

console.log(typeof new Function());//functionconsole.log(typeof new Object());//objectconsole.log(typeof new Array());//object复制代码
console.log(typeof {});//objectconsole.log(typeof []);//objectconsole.log(typeof new Object());//objectconsole.log(typeof new Array());//object复制代码

所以,怎么区分数组[]和标准对象{};

具体如何分辨,请点击查看下文提供的方法

5. 如何区分数组对象[]和普通标准对象{}

注意:typeof是无法分辨标准对象{}和数组对象[]的, 因为: {}=>new Object() []=>new Array()

console.log(typeof {});//objectconsole.log(typeof []);//objectconsole.log(typeof new Object());//objectconsole.log(typeof new Array());//object复制代码

具体如何分辨,提供以下方法,并说明原理 你只要明白一点:标准对象{}和数组对象[]就是构造器constructor或构造函数不一样,只要直接或间接知道获取他们的构造函数就可以分辨出来了

(1)

判断 引用类型 属于哪个 构造函数 的方法

var arr=[];//相当于var arr=new Array();var obj={};//相当于var obj=new Object();console.log(arr instanceof Array); //trueconsole.log(arr instanceof Object); //trueconsole.log(obj instanceof Array); //falseconsole.log(obj instanceof Object); //true复制代码

instanceof运算符用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置;

instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。

instanceof运算符用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置; 也就是说比如

var arr=[];console.log(arr instanceof Array); //true 复制代码

因为某些浏览器标识__proto__ 相当于 constructor.prototype

所以arr instanceof Array就是相当于以下代码

if(arr.__proto__ == Array.prototype)//或者if(arr.constructor.prototype == Array.prototype)复制代码

为什么会这样?这要涉及到原型与原型链:

instanceof 判断数组或对象的原理

但是由于

var arr=[];arr.__proto__ ==  Array.prototypearr.__proto__.__proto__ ==  Object.prototypearr.__proto__.__proto__.__proto__  ==  nullvar obj={};obj.__proto__ ==  Object.prototype;obj.__proto__.__proto__ == null;复制代码

由上看出,

  • 数组arr存在Array.prototype和Object.prototype 所以
console.log(arr instanceof Array); //trueconsole.log(arr instanceof Object); //true复制代码
  • 对象obj只存在Object.prototype 所以:
console.log(obj instanceof Array); //falseconsole.log(obj instanceof Object); //true复制代码

(2) constructor构造器

var arr=[];//相当于var arr=new Array();var obj={};//相当于var obj=new Object();arr.constructor==Array;//返回trueobj.constructor==Object;//返回truearr.constructor==Object;//返回falseobj.constructor==Array;//返回false复制代码

constructor 判断数组或对象的原理

也是和原型及原型链相关的

var arr=[];//相当于var arr=new Array();复制代码

arr是根据new关键字创建的数组对象,所以,arr的构造函数就是Array。

(3) constructor.name

返回构造函数的名称

var arr=[];//相当于var arr=new Array();var obj={};//相当于var obj=new Object();console.log(arr.constructor.name);//Arrayconsole.log(obj.constructor.name);//Object复制代码

(4) Object.prototype.toString.call()

Object.prototype.toString.call()返回[object constructorName]的字符串格式,这里的constructorName就是call参数的函数名

console.log(Object.prototype.toString.call([]));//返回"[object Array]"console.log(Object.prototype.toString.call({}));//返回"[object Object]"console.log(Object.prototype.toString.call("str"));//返回"[object String]"console.log(Object.prototype.toString.call(true));//返回"[object Boolean]"console.log(Object.prototype.toString.call(3));//返回"[object Number]"console.log(Object.prototype.toString.call(null));//返回"[object Null]"  一般直接判断是否为nullconsole.log(Object.prototype.toString.call(undefined));//返回"[object undefined]"一般直接判断是否为Undefined复制代码

6. JS内存

在JavaScript中,每一个变量在内存中都需要一个空间来存储。

内存空间又被分为两种,栈内存与堆内存。

栈内存 ————原始类型:

  • 存储的值大小固定

  • 空间较小

  • 可以直接操作其保存的变量,运行效率高

  • 由系统自动分配存储空间

JavaScript中的原始类型的值被直接存储在栈中,在变量定义时,栈就为其分配好了内存空间。

堆内存————引用类型:

  • 存储的值大小不定,可动态调整

  • 空间较大,运行效率低

  • 无法直接操作其内部存储,使用引用地址读取

  • 通过代码进行分配空间

相对于具有不可变性的原始类型,我习惯把对象称为引用类型,引用类型的值实际存储在堆内存中,它在栈中只存储了一个固定长度的地址,这个地址指向堆内存中的值。


-----以下内容待整理-------------


6.1 为什么要尽量使用基本变量类型,避免使用包装对象?

请先了解以下概念: 1.基本类型:String、Number、Boolean、Null、Undefined、BigInt、Symbol 2.引用类型:特殊的基本类型包装对象(String、Number、Boolean)、Object、Array、Date、Function、Error、RegExp、Math、Globle...... 3.

10. 参考

转载于:https://juejin.im/post/5d2fd6aa6fb9a07eae2a946e

你可能感兴趣的文章
Linux常用命令(四)
查看>>
Linux常用命令(六)
查看>>
Linux常用命令(六)
查看>>
Linux常用命令(八)
查看>>
Linux常用命令(七)
查看>>
Linux常用命令(九)
查看>>
Linux常用命令(十一)
查看>>
Linux常用命令(十)
查看>>
实验吧之这就是一个坑
查看>>
Linux常用命令(十二)
查看>>
Linux常用命令(十三)
查看>>
Linux常用命令(十五)
查看>>
Linux常用命令(十四)
查看>>
Linux常用命令(十七)
查看>>
Linux常用命令(十六)
查看>>
Linux常用命令(二十四)
查看>>
4种java定时器
查看>>
Vue.js 教程
查看>>
linux 设置网卡
查看>>
hive 语法 case when 语法
查看>>