一、类型与值

1.0 javaScript 七种内置类型:

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

1.1 typeof 运算符查看值的类型

typeofnull的处理显示“object”,并非显示“null”,typeof null === "object"; // true这是javaScript语言的一个bug,需要使用复合条件来检测 null 值的类型

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

function不是 JavaScript 的一个内置类型,它是 object 的一个“子类型”,但是typeof 处理函数显示"function"

typeof function a(){ /* .. */ } === "function"; // true

对于数组类型,也是 object 的一个“子类型”typeof [1,2,3] === "object"; // true

1.2 undefined 和 undeclared

  1. var a;
  2. typeof a; // "undefined"
  3. typeof b; // "undefined"

b 是 一个undeclared变量,但typeof b并没有报错,因为typeof有一个特殊的安全防范机制。利用typeof的安全防范机制,可以安全的判断,即使变量不存在也不会报错阻断程序如:

  1. // 如果DEBUG不存在js引擎就会报错
  2. if (DEBUG) {
  3. console.log( "Debugging is starting" );
  4. }
  5. // 这样是安全的
  6. if (typeof DEBUG !== "undefined") {
  7. console.log( "Debugging is starting" );
  8. }

1.3 数组

在 JavaScript 中,数组可以容纳任何类型的值,可以是字符串、 数字、对象(object),甚至是其他数组

  1. var a = [ 1, "2", [3] ];
  2. a.length; // 3
  3. a[0] === 1; // true
  4. a[2][0] === 3; // true

数组声明后即可向其中加入值,不需要预先设定大小

  1. var a = [ ];
  2. a.length; // 0
  3. a[0] = 1;
  4. a[1] = "2";
  5. a[2] = [ 3 ];
  6. a.length; // 3

含有空白或空缺单元的数组,可以正常运行

  1. var a = [ ];
  2. a[0] = 1;
  3. // 此处没有设置a[1]单元
  4. a[2] = [ 3 ];
  5. a[1]; // undefined
  6. a.length; // 3

可以包含字符串键值和属性,但这些并不计算在数组长度内

  1. var a = [ ];
  2. a[0] = 1;
  3. a["foobar"] = 2;
  4. a.length; // 1
  5. a["foobar"]; // 2
  6. a.foobar; // 2

如果字符串键值能够被强制类型转换为十进制数字的话,就会被当作数字索引来处理。

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

类数组转换成数组,ES5中可以通过数组的工具函数如Array.prototype.slice.call() ES6工具函数 Array.from(..)

1.4 字符串

字符串和数组很类似,有length 属性以及 indexOf(..)和 concat(..) 方法,但javaScript 中字符串是不可变的,字符串的成员函数不会改变其原始值,而是创建并返回一个新的字符串。可以通过“借用”数组的非变更方法来处理字符串:

  1. var a = "foo"
  2. var c = Array.prototype.join.call(a,"-")
  3. var d = Array.prototype.map.call(a,(v)=>{
  4. return v.toUpperCase() + '.'
  5. }).join("")

join数组原型对象上的方法,可以将数组转换成字符串,

  1. var a = "foo"
  2. Array.prototype.reverse.call(a)
  3. console.log(a)

在字符串上使用数组的反转函数会报错,因为字符串一旦初始化就不会改变TypeError: Cannot assign to read only property '0' of object '[object String]'

1.5 数字

tofixed(..) 方法可指定小数部分的显示位数

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

toPrecision(..) 方法用来指定有效数位的显示位数:

  1. var a = 42.59;
  2. a.toPrecision(1 ); // "4e+1"
  3. a.toPrecision( 2 ); // "43"
  4. a.toPrecision( 3 ); // "42.6"

上面的方法不仅适用于数字变量,也适用于数字常量

  1. // 无效语法,. 被视为常量 42. 的一部分
  2. 42.toFixed( 3 ); // SyntaxError
  3. // 下面的语法都有效:
  4. (42).toFixed( 3 ); // "42.000"
  5. 0.42.toFixed( 3 ); // "0.420"
  6. 42..toFixed( 3 ); // "42.000"
  7. //42..tofixed(3) 则没有问题,因为第一个 . 被视为 number 的一部分,第二个 . 是属性访问 运算符
  8. 42 .toFixed(3); // "42.000"

从 ES6 开始,严格模式(strict mode)不再支持 0363 八进制格式(新格式如 下)。0363 格式在非严格模式(non-strict mode)中仍然受支持

  1. ES6 支持以下新格式:
  2. 0o363; // 243的八进制
  3. 0O363; // 同上
  4. 0b11110011; // 243的二进制
  5. 0B11110011; // 同上

0.1 + 0.2 === 0.3; // false二进制浮点数中的 0.1 和 0.2 并不是十分精确,它们相加的结果并非刚好等于 0.3,而是一个比较接近的数字 0.30000000000000004,所以条件判断结果为 false。

怎样来判断 0.1 + 0.2 和 0.3 是否相等呢?

设置一个误差范围值,通常称为“机器精度”(machine epsilon),对javaScript 的数字来说,这个值通常是 2^-52 (2.220446049250313e-16)

从 ES6 开始,该值定义在 Number.EPSILON

  1. if (!Number.EPSILON) {
  2. Number.EPSILON = Math.pow(2,-52);
  3. }
  1. 使用 Number.EPSILON 来比较两个数字是否相等
  2. function numbersCloseEnoughToEqual(n1,n2) {
  3. return Math.abs( n1 - n2 ) < Number.EPSILON;
  4. }
  5. var a = 0.1 + 0.2;
  6. var b = 0.3;
  7. numbersCloseEnoughToEqual( a, b ); numbersCloseEnoughToEqual( 0.0000001, 0.0000002 ); // false

Number. MAX_VALUE :最大浮点数大约是 1.798e+308

Number.MIN_VALUE:最小浮点数大约是 5e-324,无限接近于 0

整数的安全范围

ES6: Number.MAX_SAFE_INTEGER:“安全”呈现的最大整数是2^53 - 1,即9007199254740991

ES6: Number. MIN_SAFE_INTEGER:最 小 整 数 是 -9007199254740991

由于 JavaScript 的数字类型无法精确呈现 64 位数值,所以必须将它们保存(转换)为字符串

整数检测

ES6 中的 Number.isInteger(..) :检测一个值是否是整数

polyfill Number.isInteger(..) 方法

  1. if (!Number.isInteger) {
  2. Number.isInteger = function(num) {
  3. return typeof num == "number" && num % 1 == 0;
  4. };
  5. }

ES6 中的 Number.isSafeInteger(..) 方法:检测一个值是否是安全的整数

polyfill Number.isSafeInteger(..) 方法:

  1. if (!Number.isSafeInteger) {
  2. Number.isSafeInteger = function(num) {
  3. return Number.isInteger( num ) &&
  4. Math.abs( num ) <= Number.MAX_SAFE_INTEGER;
  5. };
  6. }

32 位有符号整数

a | 0可以将变量a中的数值转换为32位有符号整数,因为数位运算符|只适用于32位 整数,因此与 0 进行操作即可截取 a 中 的 32 位数位。

1.6 特殊数值

undefined

  • 指从未赋值
  • 是一个标识符,可以被当作变量来使用和赋值
  • void 运算符,undefined 是一个内置标识符(除非被重新定义,见前面的介绍),它的值为 undefined, 通过 void 运算符即可得到该值。
  1. var a = 42;
  2. console.log( void a, a ); // undefined 42
  3. //void并不改变表达式的结果, 只是让表达式不返回值:

null

  • null 指空值(empty value)
  • 曾赋过值,但是目前没有值
  • null 是一个特殊关键字,不是标识符

NaN

  • 不是数字的数字
  • 是一个“警戒值”(sentinel value,有特殊用途的常规值),用于指出数字类型中的错误 情况,即“执行数学运算没有成功,这是失败后返回的结果”。
  • NaN是一个特殊值,它和自身不相等,是唯一一个非自反
  1. var a = 2 / "foo";
  2. var b = "foo";
  3. a; // NaN b; "foo"
  4. window.isNaN( a ); // true
  5. window.isNaN( b );// true

isNaN(..) 检查参数是否不是 NaN,也不是数字,"foo" 不是一个数字,但是它也不是 NaN

ES6工具函数 Number.isNaN(..)

  1. if (!Number.isNaN) {
  2. Number.isNaN = function(n) {
  3. return (
  4. typeof n === "number" && window.isNaN( n )
  5. }
  6. var a = 2 / "foo"
  7. var b ="foo"
  8. ); };
  9. Number.isNaN( a ); // true
  10. Number.isNaN( b );// false

Infinity

  1. var a = 1 / 0; // Infinity
  2. var b = -1 / 0; // -Infinity

零值

为什么会有 -0 ?

有些应用程序中的数据需要以级数形式来表示(比如动画帧的移动速度),数字的符号位 (sign)用来代表其他信息(比如移动的方向)。此时如果一个值为 0 的变量失去了它的符号位,它的方向信息就会丢失。所以保留 0 值的符号位可以防止这类情况发生。

区分 -0 和 0方法:

  1. function isNegZero(n) {
  2. n = Number( n );
  3. return (n === 0) && (1 / n === -Infinity);
  4. }
  5. isNegZero( -0 ); // true
  6. isNegZero( 0 / -3 ); // true
  7. isNegZero( 0 );// false

特殊等式

Es6工具方法 Object.is(..)

  1. var a = 2 / "foo";
  2. var b = -3 * 0;
  3. Object.is( a, NaN );
  4. Object.is( b, -0 );
  5. Object.is( b, 0 );
  1. if (!Object.is) {
  2. Object.is = function(v1, v2) {
  3. // 判断是否是-0
  4. if (v1 === 0 && v2 === 0) {
  5. return 1 / v1 === 1 / v2;
  6. }
  7. // 判断是否是NaN
  8. if (v1 !== v1) {
  9. return v2 !== v2;
  10. }
  11. // 其他情况
  12. return v1 === v2;
  13. };
  14. }

1.7 值和引用

  1. var a = 2;
  2. var b = a; // b是a的值的一个副本
  3. b++;
  4. a; // 2
  5. b; // 3
  6. var c = [1,2,3];
  7. var d = c; // d是[1,2,3]的一个引用
  8. d.push( 4 );
  9. c; // [1,2,3,4]
  10. d; // [1,2,3,4]

简单值(即标量基本类型值,scalar primitive)总是通过值复制的方式来赋值 / 传递,包括 null、undefined、字符串、数字、布尔和 ES6 中的 symbol。

复合值(compound value)——对象和函数,则总 是通过引用复制的方式来赋值 / 传递。

引用指向的是值本身而非变量,所以一个引用无法更改另一个引用的指向

  1. var a = [1,2,3];
  2. var b = a;
  3. a; // [1,2,3]
  4. b; // [1,2,3]
  5. // 然后
  6. b = [4,5,6];
  7. a; // [1,2,3]
  8. b; // [4,5,6]

b=[4,5,6] 并不影响 a 指向值 [1,2,3],除非 b 不是指向数组的引用,而是指向 a 的指针,在 javaScript 中不存在指针

  1. function foo(x) {
  2. x.push( 4 );
  3. x; // [1,2,3,4]
  4. // 然后
  5. x = [4,5,6];
  6. x.push( 7 );
  7. x; // [4,5,6,7]
  8. }
  9. var a = [1,2,3];
  10. foo( a );
  11. a; // 是[1,2,3,4],不是[4,5,6,7]

向函数传递 a 的时候,实际是将引用 a 的一个复本赋值给 x,而 a 仍然指向 [1,2,3]。 在函数中我们可以通过引用x来更改数组的值(push(4)之后变为[1,2,3,4])。但x = [4,5,6] 并不影响 a 的指向,所以 a 仍然指向 [1,2,3,4]。不能通过引用 x 来更改引用 a 的指向,只能更改 a 和 x 共同指向的值。

foo( a.slice() );

slice(..) 不带参数会返回当前数组的一个浅复本(shallow copy)。由于传递给函数的是指向该复本的引用,所以 foo(..) 中的操作不会影响 a 指向的数组。

如果要将标量基本类型值传递到函数内并进行更改,就需要将该值封装到一个复合值(对象、数组等)中,然后通过引用复制的方式传递。

  1. function foo(wrapper) {
  2. wrapper.a = 42;
  3. }
  4. var obj = {
  5. a: 2
  6. };
  7. foo( obj );
  8. obj.a; // 42

总结

  • 赋值 / 参数传递是通过引用复制还是值复制完全由值的类型来决定,所以使用哪种类型也间接决定了赋值 / 参数传递的方式。
  • null 类型只有一个值 null,undefined 类型也只有一个值 undefined。所有变量在赋值之 前默认值都是 undefined。void 运算符返回 undefined。
  • 数字类型有几个特殊值,包括 NaN(意指“not a number”,更确切地说是“invalid number”)、+Infinity、-Infinity 和 -0。

【你不知道的javaScript 中卷 笔记1】javaScript中的类型与值的更多相关文章

  1. JavaScript进阶内容笔记1:各种对象类型判断

    该文章主要用来介绍JavaScript中常用的一些对象检测判断方法,整理资源来自书本和网络,如有错误或说明不详之处,望评论提出,本菜定提名感谢……(本文章知识比较基础,大牛请提些意见再绕道,三克油^_ ...

  2. 【你不知道的javaScript 中卷 笔记2】javaScript中的类型转换

    1.1 对象内部属性 [[Class]] 常见的原生函数: String() Number() Boolean() Array() Object() Function() RegExp() Date( ...

  3. 《高性能JavaScript》学习笔记——日更中

    ------------------2016-7-20更------------------ 最近在看<高性能JavaScript>一书,里面当中,有讲很多提高js性能的书,正在看的过程中 ...

  4. EF中System.Data.Entity.Internal.AppConfig的类型初始值设定项引发异常

    使用Entity的时候遇到的一个错 问题出在项目的App.config中 解决: 1.configSections要写在最顶端 2. 当中的incariantName会变成incariantNodeN ...

  5. 《你不知道的JavaScript(中卷)》读书笔记

    中卷有点无聊,不过也是有干货的,但是好像要背一下的样子.不过作者大大都夸我是“优秀的开发人员”了,肯定要看完呀~~ 开发人员觉得它们太晦涩,很难掌握和运用,弊(导致bug)大于利(提高代码可读性).这 ...

  6. 从头开始学JavaScript 笔记(一)——基础中的基础

    原文:从头开始学JavaScript 笔记(一)--基础中的基础 概要:javascript的组成. 各个组成部分的作用 . 一.javascript的组成   javascript   ECMASc ...

  7. 《编写可维护的javascript》读书笔记(中)——编程实践

    上篇读书笔记系列之:<编写可维护的javascript>读书笔记(上) 上篇说的是编程风格,记录的都是最重要的点,不讲废话,写的比较简洁,而本篇将加入一些实例,因为那样比较容易说明问题. ...

  8. 学习笔记:JavaScript传参方式———ECMAScript中所有函数的参数都是按值传递

    我们把命名参数(arguments)视为局部变量,在向参数传递基本类型值时,如同基本类型变量的复制一样,传递一个副本,参数在函数内部的改变不会影响外部的基本类型值.如: function add10( ...

  9. 编程笔记:JavaScript 中的类型检查

    在Badoo的时候我们写了大量的JS脚本,光是在我们的移动web客户端上面就有大概60000行,可想而知,维护这么多JS可是相当具有挑战性的.在写如上规模js脚本客户端应用的时候我们必须对一件事保持警 ...

随机推荐

  1. Metasploit学习笔记(一) Samba服务 usermap_script安全漏洞相关信息

    一.Samba介绍 Samba是linux和unix系统上实现smb协议的一个免费软件,由客户机和服务器构成.SMB是一种在局域网上实现共享文件和打印机的协议.存在一个服务器,客户机通过该协议可以服务 ...

  2. Android 7.0新特性“Nougat”(牛轧糖)。

    1.Unicode 9支持和全新的emoji表情符号 Android Nougat将会支持Unicode 9,并且会新增大约70种emoji表情符号.这些表情符号大多数都是人形的,并且提供不同的肤色, ...

  3. [RHEL8]关闭SELinux(同CentOS7)

    修改配置文件(永久修改) # vi /etc/selinux/config SELINUX=disabled # 关闭 SELINUX=enforcing # 开启 命令方式(临时修改重启失效) # ...

  4. 杭电-------2055An Easy Problem(C语言)

    #include<stdio.h> int main() { int m; int i; scanf("%d", &m); ]; int y; int z; ; ...

  5. 1Python学习CentOS 7 Linux环境搭建

    鉴于python3目前已成流行之势,而各发行版Linux依然是自带python2.x,笔者尝试在centos7下,部署Python3.x与2.x共存环境 本文参考博主良哥95网址https://blo ...

  6. C++ Primer抄书笔记(二)——变量和基本类型(下)

    四.const限定符[引用/指针/顶层/常量表达式] const对象值不变,必须初始化,能完成此type的大部分operation. 一般,多文件独立变量,编译初始化仅文件内有效: 除非,(条件:初值 ...

  7. 正则表达式验证IP地址(绝对正确)

    正则验证合法_有效的IP地址(ipv4/ipv6) 不墨迹直接上代码: 正则表达式: /^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[ ...

  8. fancybox图片灯箱功能

    fancybox图片灯箱功能 在页面中引入几个文件 <script src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery ...

  9. 【读书笔记】https://source.android.google.cn/devices/bootloader

    https://source.android.google.cn/devices/bootloader 本文主要记录aosp官网关于bootloader的相关资料 Bootloader A bootl ...

  10. spark 报错 InvalidClassException: no valid constructor

    2019-03-19 02:50:24 WARN TaskSetManager:66 - Lost task 1.0 in stage 0.0 (TID 1, 1.2.3.4, executor 1) ...