第一章 类型

第一章 类型

js中的类型

js语言中的类型分为基本类型和对象类型

类型有:(除对象外,其他统称为基本类型)

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

如何判别值的类型

typeof运算符可以查看值的类型,他返回的是类型的字符串值,但是这七种值和他们的字符串值并不一一对应

typeof undefined === "undefined"; // true

typeof true === "boolean"; // true

typeof 42 === "number"; // true

typeof "42" === "string"; // true

typeof { life: 42 } === "object"; // true

// ES6中新加入的类型

typeof Symbol() === "symbol"; // true

以上六种判别均正常,但是null例外


typeof null === "object"; // true

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


var a = null;
(!a && typeof a === "object"); // true

还有一种情况:


typeof function a(){ /* .. */ } === "function"; // true
typeof [1,2,3] === "object"; // true

undefined 和 undeclared

变量在未持有值的时候为 undefined。此时 typeof 返回 "undefined

var a;
typeof a; // "undefined"
var b = 42;
var c;
// later
b = c;
typeof b; // "undefined"
typeof c; // "undefined"

大多数开发者倾向于将 undefined 等同于 undeclared(未声明),但在 JavaScript 中它们完全
是两回事。

已在作用域中声明但还没有赋值的变量,是 undefined 的。

相反,还没有在作用域中声明过的变量,是 undeclared 的。

var a;
a; // undefined
b; // ReferenceError: b is not defined

更让人抓狂的是 typeof 处理 undeclared 变量的方式。例如:

var a;
typeof a; // "undefined"
typeof b; // "undefined"

对于 undeclared(或者 not defined)变量,typeof 照样返回 "undefined"。

请注意虽然 b 是
一个 undeclared 变量,但 typeof b 并没有报错。这是因为 typeof 有一个特殊的安全防范机制


typeof Undeclared

该安全防范机制对在浏览器中运行的 JavaScript 代码来说还是很有帮助的,

因为多个脚本文件会在共享的全局命名空间中加载变量。


// 这样会抛出错误
if (DEBUG) {
 console.log( "Debugging is starting" );
}
// 这样是安全的
if (typeof DEBUG !== "undefined") {
 console.log( "Debugging is starting" );
}

//这不仅对用户定义的变量(比如 DEBUG)有用,对内建的 API 也有帮助:
if (typeof atob === "undefined") {
 atob = function() { /*..*/ };
}

还有一种不用通过 typeof 的安全防范机制的方法,就是检查所有全局变量是否是全局对象
的属性,浏览器中的全局对象是 window。所以前面的例子也可以这样来实现:

if (window.DEBUG) {
 // ..
}
if (!window.atob) {
 // ..
}

与 undeclared 变量不同,访问不存在的对象属性(甚至是在全局对象 window 上)不会产生
ReferenceError 错误。

一些开发人员不喜欢通过 window 来访问全局对象,尤其当代码需要运行在多种 JavaScript
环境中时(不仅仅是浏览器,还有服务器端,如 node.js 等),因为此时全局对象并非总是
window。


小结

JavaScript 有 七 种 内 置 类 型:null、undefined、boolean、number、string、object 和
symbol,可以使用 typeof 运算符来查看。

变量没有类型,但它们持有的值有类型。类型定义了值的行为特征。

很多开发人员将 undefined 和 undeclared 混为一谈,但在 JavaScript 中它们是两码事。
undefined 是值的一种。undeclared 则表示变量还没有被声明过。

遗憾的是,JavaScript 却将它们混为一谈,在我们试图访问 "undeclared" 变量时这样报错:ReferenceError: a is not defined,并且 typeof 对 undefined 和 undeclared 变量都返回
"undefined"。

然而,通过 typeof 的安全防范机制(阻止报错)来检查 undeclared 变量,有时是个不错的
办法。


第二章 值

数组

和其他强类型语言不同,在 JavaScript 中,数组可以容纳任何类型的值,可以是字符串、
数字、对象(object),甚至是其他数组(多维数组就是通过这种方式来实现的)

使用 delete 运算符可以将单元从数组中删除,但是请注意,单元删除后,数
组的 length 属性并不会发生变化。第 5 章将详细介绍 delete 运算符。

数组通过数字进行索引,但有趣的是它们也是对象,所以也可以包含字符串键值和属性
(但这些并不计算在数组长度内)


var a = [ ];
a[0] = 1;
a["foobar"] = 2;
a.length; // 1
a["foobar"]; // 2
a.foobar; // 2

这里有个问题需要特别注意,如果字符串键值能够被强制类型转换为十进制数字的话,它
就会被当作数字索引来处理。


var a = [ ];
a["13"] = 42;
a.length; // 14

在数组中加入字符串键值 / 属性并不是一个好主意。建议使用对象来存放键值 / 属性值,
用数组来存放数字索引值。


类数组

有时需要将类数组(一组通过数字索引的值)转换为真正的数组,这一般通过数组工具函数(如 indexOf(..)、concat(..)、forEach(..) 等)来实现。

例如,一些 DOM 查询操作会返回 DOM 元素列表,它们并非真正意义上的数组,但十分
类似。另一个例子是通过 arguments 对象(类数组)将函数的参数当作列表来访问(从
ES6 开始已废止)。

工具函数 slice(..) 经常被用于这类转换:

function foo() {
 var arr = Array.prototype.slice.call( arguments );
 arr.push( "bam" );
 console.log( arr );
}
foo( "bar", "baz" ); // ["bar","baz","bam"]

用 ES6 中的内置工具函数 Array.from(..) 也能实现同样的功能:

...
var arr = Array.from( arguments );
...

字符串

许多数组函数用来处理字符串很方便。虽然字符串没有这些函数,但可以通过“借用”数
组的非变更方法来处理字符串:

var a = "foo";
var b = ["f","o","o"];
a.join; // undefined
a.map; // undefined
var c = Array.prototype.join.call( a, "-" );
var d = Array.prototype.map.call( a, function(v){
 return v.toUpperCase() + ".";
} ).join( "" );
c; // "f-o-o"
d; // "F.O.O."

另一个不同点在于字符串反转(JavaScript 面试常见问题)。数组有一个字符串没有的可变更成员函数 reverse():

a.reverse; // undefined
b.reverse(); // ["!","o","O","f"]
b; // ["f","O","o","!"]

可惜我们无法“借用”数组的可变更成员函数,因为字符串是不可变的:

Array.prototype.reverse.call( a );
// 返回值仍然是字符串"foo"的一个封装对象(参见第3章):(
// 在浏览器中会报以下错误
20200824162257

一个变通(破解)的办法是先将字符串转换为数组,待处理完后再将结果转换回字符串:

这种方法的确简单粗暴,但对简单的字符串却完全适用

var c = a
// 将a的值转换为字符数组
.split( "" )
// 将数组中的字符进行倒转
.reverse()
// 将数组中的字符拼接回字符串
.join( "" );
c; // "oof"

数字

数字的语法

var a = 42; 
var b = 42.3;

小数点前面的 0 可以省略:

var a = 42.0; 
var b = 42.;

默认情况下大部分数字都以十进制显示,小数部分最后面的 0 被省略,如:

var a = 42.300; 
var b = 42.0; 
a; // 42.3 
b; // 42

特别大和特别小的数字默认用指数格式显示,与 toExponential() 函数的输出结果相同。
例如:

var a = 5E10; 
a; // 50000000000 
a.toExponential(); // "5e+10" 
var b = a * a; 
b; // 2.5e+21 
var c = 1 / a; 
c; // 2e-11

由于数字值可以使用 Number 对象进行封装(参见第 3 章),因此数字值可以调用 Number.prototype 中的方法(参见第 3 章)。例如,tofixed(..) 方法可指定小数部分的显示位数:

var a = 42.59; 
a.toFixed( 0 ); // "43" 
a.toFixed( 1 ); // "42.6" 
a.toFixed( 2 ); // "42.59" 
a.toFixed( 3 ); // "42.590" 
a.toFixed( 4 ); // "42.5900"

请注意,上例中的输出结果实际上是给定数字的字符串形式,如果指定的小数部分的显示
位数多于实际位数就用 0 补齐。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349