前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JS篇之数据类型那些事儿

JS篇之数据类型那些事儿

作者头像
前端柒八九
发布2022-08-25 14:09:56
5310
发布2022-08-25 14:09:56
举报
文章被收录于专栏:柒八九技术收纳盒

一语中的

  1. JS = ECMAScript + DOM + BOM
  2. DOM 并非只能通过 JS 访问
  3. JS是「动态弱类型」语言
  4. 每个「变量」只不过是一个用于保存任意值的命名占位符
  5. 实例与构造函数原型之间有直接的联系,但实例与构造函数之间没有
  6. 基本类型是没有任何属性和方法
  7. 对象其实就是一组数据和功能的集合

文章概要

  • JS组成
  • JS数据类型(7+1)
  • 类型转换(装箱/拆箱)

JS组成

其实这是一个很容易忽略的问题。俗话说,最熟悉的陌生人说的就是这种情况。

「浏览器环境下」JS = ECMAScript + DOM + BOM

我们来简单介绍下。(后期会单独针对BOM/DOM进行分析)

ECMAScript

JS的核心部分,即 ECMA-262 定义的语言,并不局限于 Web 浏览器。

Web 浏览器只是 ECMAScript 实现可能存在的一种*「宿主环境(host environment)」。而宿主环境提供ECMAScript 的基准实现和与环境自身交互必需的扩展。(比如 DOM 使用 ECMAScript 核心类型和语法,提供特定于环境的额外功能)。

像我们比较常见的Web 浏览器、 Node.js和即将被淘汰的 Adobe Flash都是ECMA的宿主环境。

ECMAScript 只是对实现ECMA-262规范的一门语言的称呼, JS 实现了ECMAScript,Adobe ActionScript 也实现ECMAScript。

文档对象模型(DOM)

DOM是一个应用编程接口(API),通过创建表示文档的树,以一种「独立于平台和语言」的方式访问和修改一个页面的内容和结构。

在HTML文档中,Web开发者可以使用JS来CRUD DOM 结构,其主要的目的是「动态」改变HTML文档的结构。

「DOM 将整个页面抽象为一组分层节点」

DOM 并非只能通过 JS 访问, 像可伸缩矢量图(SVG)、数学标记语言(MathML)和同步多媒体集成语言(SMIL)都增加了该语言独有的 DOM 方法和接口。

浏览器对象模型(BOM)

用于支持访问和操作浏览器的窗口。

针对浏览器窗口和子窗口(frame)提供了

  • 弹出新浏览器窗口的能力
  • 移动、缩放和关闭浏览器窗口的能力
  • navigator 对象,提供关于浏览器的详尽信息
  • location 对象,提供浏览器加载页面的详尽信息
  • screen 对象,提供关于用户屏幕分辨率的详尽信息
  • performance 对象,提供浏览器内存占用、导航行为和时间统计的详尽信息
  • 「对 cookie 的支持」
  • 其他自定义对象,如 XMLHttpRequest 和 IE 的 ActiveXObject

JS数据类型

每种编程语言都具有内建的数据类型,而根据使用数据的方式从两个不同的维度将语言进行分类。

  1. 「动态/静态」
  • 动态类型:运行过程中需要检查数据类型
  • 静态类型:使用之前就需要确认其变量数据类型
  1. 「强/弱」
  • 强类型:不支持隐式类型转换
  • 弱类型:支持隐式类型转换

❝隐式类型转换 :在赋值过程中,编译器会把 int 型的变量转换为 bool 型的变量 ❞

通过上述的介绍和平时大家的使用JS的数据类型发现。

JS是「动态弱类型」语言。

由于JS的语言特性,我们可以进而得出另外一个结论:每个「变量」只不过是一个用于保存任意值的命名占位符。

而谈到JS数据类型,就绕不开针对数据的分类。你没猜错,还是一样的配方,大家熟悉的味道。

ECMAScript 有8 种数据类型

  1. Undefined
  2. Null
  3. Boolean
  4. String
  5. Number
  6. Symbol (ES6新增)
  7. 「BigInt」 (ES2020新增)
  8. Object (基本引用类型、)

根据「数据存储位置」的不同,我们将JS数据类型分为两大类:

  1. 基本数据类型(primary) 存放在栈内存中,类型1-7
  2. 复杂数据类型/引用类型 存放在堆内存中, 类型8

针对老生常谈的问题,我们来搞点不一样的。

JS 判断数据类型方式(4种)

该问题在一些面试题中,出现的频率还挺高。(敲黑板,考试要考!)

1. typeof

typeof 操作符可以确定值的「原始类型」,也就是说,该操作只能区分基本数据类型,而对于复杂数据类型就鞭长莫及了。

代码语言:javascript
复制
let un, nu =null, bo = true, st = '789', 
    num = 789,sy = Symbol('789'),bi = 789n;
typeof un; // "undefined"
typeof nu; // "object" 这是一个特例,或者说null就是一个特例
typeof bo; //"boolean"
typeof st; // "string"
typeof num;// "number"
typeof sy; // "symbol"
typeof bi; // "bigint"

❝特例分析:null值表示一个空对象指针。所以针对typeof null 返回了一个"object"。 ❞

2. Object.prototype.toString.call(xx)

若参数(xx)不为 null 或 undefined,则将参数转为对象,再作判断。转为对象后,取得该对象的 [Symbol.toStringTag] 属性值(可能会遍历原型链)作为 tag,然后返回 "[object " + tag + "]" 形式的字符串。

针对基本数据类型,通过装箱过程转为对象类型。

代码语言:javascript
复制
Object.prototype.toString.call(null) //[ojbect Null]
Object.prototype.toString.call(undefined) //[object Undefined]
Object.prototype.toString.call(true) // [object Boolean]
Object.prototype.toString.call(()=>{}) // [object Function]

通过Object.prototype.toString可以将数据类型很容易的分开。但是,每次进行判断的时候,多了一堆额外的信息。所以,我们可以对该方法进行改进。

代码语言:javascript
复制
function getDataType(type){
  return Object.prototype.toString.call(type)
  .split(' ')[1]
  .slice(0,-1)
  .toLocaleLowerCase();
}

getDataType(null) //null
getDataType(undefined) // undefined
getDataType(true) // boolean
getDataType(()=>{}) // function

3. instanceof

在一些资料中讲到,instanceof 是用来判断 a 是否为 B 的实例,表达式为:a instanceof B,如果 a 是 B 的实例,则返回 true,否则返回 false

其实这句话是不严谨的。准确的描述应该是:a instanceof B 用于判断实例a的原型链中出现过相应的构造函数B,则 instanceof 返回 true 。instanceof 判断的是 a和B是否有血缘关系,而不是仅仅根据是否是父子关系。

代码语言:javascript
复制
let ar = [];
ar instanceof Array // true
ar instanceof Object // true  如果按照实例的关系的话,这应该返回false

多说一句,在ES6中instanceof 操作符会使用 Symbol.hasInstance 函数来确定关系。

这个属性定义在 「Function 的原型」上,因此默认在所有函数和类上都可以调用。

代码语言:javascript
复制
function Car() {} 
let c = new Car(); 
console.log(Car[Symbol.hasInstance](c)); // true 

我们可以通过重新定义该方法,来改变instanceof的值。

代码语言:javascript
复制
class Parent{} 
class Child extends Parent { 
  static [Symbol.hasInstance]() { 
   return false; 
  }  
} 
let c = new Child(); 
console.log(Parent[Symbol.hasInstance](c)); // true 
console.log(c instanceof Parent); // true 
// 
console.log(Child[Symbol.hasInstance](c)); // false 
console.log(c instanceof Child); // false

(这里再埋一个伏笔,后期会有针对原型的文章)

4. constructor

只要创建一个函数,就会按照特定的规则为这个函数创建一个 prototype 属性(指向原型对象)。默认情况下,所有原型对象「自动」获得一个名为 constructor 的属性,指回与之关联的构造函数。

每次调用构造函数创建一个新实例,实例的内部[[Prototype]]指针就会被赋值为构造函数的原型对象。

❝实例与构造函数原型之间有直接的联系,但实例与构造函数之间没有 ❞

所以,可以通过实例和构造函数原型的关系,来判断是否实例类型。

代码语言:javascript
复制
''.constructor === String; // true;
true.constructor === Boolean; // true;
new Number(1).constructor === Number // number 类型存在包装对象

null/undefined是一个「假值」,没有对应包装对象(无法进行装箱操作),也不是任何构造函数的实例。所以,不存在原型,即,无法使用constructor判断类型。 ❞

类型转换(装箱/拆箱)

「基本类型是没有任何属性和方法」

此时,有人就会有一个疑问,当定义了let str = '789';,此时可以通过str进行属性和方法调用。这不是和上面的那个相悖嘛。

其实,针对基本类型的属性和方法的调用,都是在基本类型的包装对象上进行操作。

装箱转换

每一种基本类型 Number、String、Boolean、Symbol 在对象中都有对应的类,所谓装箱转换,正是把基本类型转换为对应的对象,它是类型转换中一种相当重要的种类。

代码语言:javascript
复制
let str = '789';
str.length; //3 属性调用
str.slice(1); // "89"  方法调用

=======等价于
let strObj = new String(789);
strObj.length; //3
strObj.slice(1); //"89"

拆箱转换

在 JavaScript 标准中,规定了 ToPrimitive 函数,它是对象类型到基本类型的转换(即,拆箱转换)。

对象到 String 和 Number 的转换都遵循“先拆箱再转换”的规则。通过拆箱转换,把对象变成基本类型,再从基本类型转换为对应的 String 或者 Number。

拆箱转换会尝试调用 valueOf 和 toString 来获得拆箱后的基本类型。如果 valueOf 和 toString 都不存在,或者没有返回基本类型,则会产生类型错误 TypeError

代码语言:javascript
复制
let o = {
      valueOf : () => {console.log("valueOf"); return {}},
      toString : () => {console.log("toString"); return {}}
     }
 
  o * 2
 // valueOf
 // toString
 // TypeError

对象的Symbol.toPrimitive属性,指向一个方法。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。

代码语言:javascript
复制
let o = {
        valueOf : () => {console.log("valueOf"); return {}},
        toString : () => {console.log("toString"); return {}}
    }
 
 o[Symbol.toPrimitive] = () => {console.log("toPrimitive"); return "hello"}
 
 console.log(o + "")
 // toPrimitive
 // hello
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-01-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端柒八九 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一语中的
  • 文章概要
  • JS组成
    • ECMAScript
      • 文档对象模型(DOM)
        • 浏览器对象模型(BOM)
        • JS数据类型
          • JS 判断数据类型方式(4种)
            • 1. typeof
            • 2. Object.prototype.toString.call(xx)
            • 3. instanceof
            • 4. constructor
        • 类型转换(装箱/拆箱)
          • 装箱转换
            • 拆箱转换
            相关产品与服务
            数据保险箱
            数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档