前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >你不知道的 JavaScript 中卷(1、类型)

你不知道的 JavaScript 中卷(1、类型)

作者头像
Karl Du
发布2023-10-20 19:00:02
2830
发布2023-10-20 19:00:02
举报
文章被收录于专栏:Web开发之路

前言

最近在读《你不知道的 JavaScript 中卷》,不会像上卷那样通篇仔细阅读一章一章的写博客了,因为我没那么多精力了。我每天花一点时间去写一些简单且篇幅不长的博客,这样在地铁或在电梯里花一分钟就可以读完。

该书第一章就是讲js的类型,学习难度不大,基本上就是复习了一遍。我结合我的实际开发,把一些工作中常见的问题和技巧都写了下来,希望能帮助到你们。

类型之争

JavaScript是一门弱类型语言,所以非常灵活,如下所示:

代码语言:javascript
复制
var data = http.get('/post/data'); // [{ title: "类型", content: "..."}]
data = JSON.parse(data);

上面一个示例,我们先是通过http调用得到一个json数据,然后解析得到一个数组,期间我们只声明了一个变量data

再看看强类型语言C#是怎么去实现上面这段代码:

代码语言:javascript
复制
class Post
{
    string title { get; set; }
  string content { get; set; }
}
var json = HttpUtil.get('/post/data');
var data = JsonConvert.DeserializeObject<Post>(json);

强类型的语言更为严谨,json声明为一个String类型变量后,如果你赋值其他类型的值,编译器就会提示错误。且,同样是Json解析,C#还需要提前声明好了Post类,才能通过泛型去解析。

我们比较一下得出以下结论:

1、弱类型语言灵活,可以通过两行代码实现十几行代码的功能

2、强类型语言非常啰嗦,但是可以使得开发过程中手误导致的意外错误(变量名写错)不会跑到线上

类型转换

我们在实际开发中经常会去转换变量类型,比如前端开发人员对接后端接口的时候,有的时候需要把number类型的数据转换成string,或者就是把string类型的数字转换成number,还有一种常见的场景就是把日期字符串转换成Date类型。

前面我们提到,JavaScript是一门弱类型语言,所以在js中,变量是没有类型的,只有值才有类型。变量既然没有类型限制,我们就可以通过一些强制转换类型的函数实现类型转换。

显示类型转换

在某些情况下,程序员需要手动将一个类型转换为另一个类型。例如,您可能需要将一个字符串转换为一个数字,或者将一个布尔值转换为一个字符串。

代码语言:javascript
复制
// 将字符串转换为数字
var str = "42";
var num = Number(str); // 显式转换,str被转换为数字
console.log(num); // 输出: 42

// 将布尔值转换为字符串
var bool = true;
var str = String(bool); // 显式转换,bool被转换为字符串
console.log(str); // 输出: "true"

隐式类型转换

JavaScript引擎在必要时会自动将一个类型转换为另一个类型,不需要程序员手动进行转换。例如,当您将数字与字符串相加时,数字会自动转换为字符串。

代码语言:javascript
复制
var num = 42;
var str = "The answer is " + num; //隐式转换,num被转换为字符串
console.log(str); // 输出: "The answer is 42"

强制类型转换

强制类型转换是一种特殊的显式类型转换,它是将一个非布尔类型的值转换为布尔类型的值。在JavaScript中,有一些值会被转换为false,这些值被称为“假值”,其他所有值都被转换为true

代码语言:javascript
复制
// 强制类型转换,num被转换为布尔值
var num = 0;
var bool = Boolean(num);
console.log(bool); // 输出: false

类型判断

类型判断常见于我们封装的函数对入参的一些检查,如下:

代码语言:javascript
复制
function httpGet(url, params) {
  if(typeof str !== 'string')
    return 'url格式错误'
  if(typeof params !== 'object')
    return 'params格式错误'
  // ....
}

这段代码,看上去没问题,实际上并没有达到我们想要的一个效果

代码语言:javascript
复制
httpGet('/post/data', { category: 'js' }); // 合法
httpGet('/post/data', [{ category: 'js' }]); // 合法

我们注意到,上面这个代码,我们实际上是期望params是一个对象,但是数组类型的入参并没有被类型判断出来

这种bug对于js新手程序员来说,是经常犯的错误。实际上,这不仅是你没有好好学习JavaScript的类型,同时也是js语言本身的缺陷

下面,我们简单回顾一下js的对象类型

内置类型

先了解一下JavaScript的七种类型

  • 空值(null)
  • 未定义(undefined)
  • 布尔值(boolean)
  • 数字(number)
  • 字符串(string)
  • 对象(object)
  • 符号(symbol)

除对象外,其他统称为基本类型

我们用typeof分别看一下值的类型,它返回的是类型的字符串。有意思的是,这七种类型和它们的字符串值并不一一对应:

代码语言:javascript
复制
typeof undefined === "undefined" // true
typeof true === "boolean"        // true
typeof 42 === "number"           // true
typeof "42" === "string"         // true
typeof { life: 42 } === "object" // true
typeof Symbol() === "symbol"     // true
console.log(typeof null)         // object

以上六种类型均有同名的字符串值与之对应,但是null却对应object类型,实际上,这是一个历史遗留bug,现在已经有无数JS项目在全球各地运行着,一旦修复,造成的影响太大,所以ECMA不会去修复这个bug了,可以说,这个问题将永远不会被修复

我们需要使用符合条件来检测null值的类型:

代码语言:javascript
复制
var a = null;
(!a && typeof a === "object") // true

对象子类型

我们知道Array、Date、String、Number等等这些对象子类型,它们在typeof下结果是什么呢?

代码语言:javascript
复制
typeof [] // object
typeof new Date() // object
typeof new String('foo') // object

我们看到,返回结果都是:object。这是因为它们都是object的子类型,所以返回的是object

我们知道在JavaScript里“万物皆类型”(并不完全正确),而函数是一等公民,那么函数的返回是什么呢?

代码语言:javascript
复制
function foo() {}
typeof foo // function

到这里,我们明白了对象子类型用typeof判断是无效的,那怎么办

toString

toString.call()是一种常见的JavaScript技巧,用于确定变量的数据类型。它是通过调用内置Object.prototype.toString()方法来实现的,该方法返回一个表示该对象的类型的字符串。

以下是使用toString.call()方法的示例:

代码语言:javascript
复制
var num = 42;
var str = "Hello, world!";
var arr = [1, 2, 3];

console.log(toString.call(num)); // 输出: "[object Number]"
console.log(toString.call(str)); // 输出: "[object String]"
console.log(toString.call(arr)); // 输出: "[object Array]"

使用toString.call()的好处在于它对所有类型的值都有效,包括原始类型和对象类型。因此,您可以使用它来判断一个值是否是数组、日期、正则表达式等等。

例如,以下是使用toString.call()来判断一个值是否是数组的示例:

代码语言:javascript
复制
var arr = [1, 2, 3];

if (toString.call(arr) === "[object Array]") {
  console.log("arr is an array");
} else {
  console.log("arr is not an array");
}

好,到此为止,问题完美解决了,我们可以通过toString.call来判断这个变量是不是数组

第三方库

如今,有很多第三方库可以帮助我们实现判断变量类型,以下是一些常用的:

Lodash:Lodash是一个实用的JavaScript工具库,提供了许多常见操作的函数,包括类型检查。它的_.is*()函数系列可用于检查各种类型,例如_.isNumber()_.isString()_.isObject()等等。

代码语言:javascript
复制
var _ = require('lodash');

console.log(_.isNumber(42)); // 输出: true
console.log(_.isString("Hello, world!")); // 输出: true
console.log(_.isObject({ key: "value" })); // 输出: true

jQuery:jQuery是一个流行的JavaScript库,用于操作DOM元素和处理事件等。它也提供了一些类型检查函数,例如.isNumeric()、.isArray()等等。

代码语言:javascript
复制
console.log($.isNumeric(42)); // 输出: true
console.log($.isArray([1, 2, 3])); // 输出: true

Underscore.js:Underscore.js是另一个常用的JavaScript工具库,类似于Lodash,提供了许多实用函数,包括类型检查函数。

代码语言:javascript
复制
var _ = require('underscore');

console.log(_.isNumber(42)); // 输出: true
console.log(_.isString("Hello, world!")); // 输出: true
console.log(_.isObject({ key: "value" })); // 输出: true
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023/04/01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 类型之争
  • 类型转换
    • 显示类型转换
      • 隐式类型转换
        • 强制类型转换
        • 类型判断
          • 内置类型
            • 对象子类型
              • toString
                • 第三方库
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档