第一章 类型

第一章 类型

  • 跳转到sessionone

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 补齐。

你可能感兴趣的:(第一章 类型)