《你不知道的JavaScript》整理(五)——值与原生函数
一、值
1)数字
JavaScript只有一种数值类型:number(数字),包括“整数”和带小数的十进制数。
//数字的语法
var a = 5E10; //
a.toExponential(); // "5e+10"
var b = a * a; // 2.5e+21
var c = 1 / a; // 2e-11
var d = 0.42;
var e = .42; //数字前面的0可以省略
var f = 42.; //小数点后小数部分最后面的0也可以省略
由于数字值可以使用Number对象进行封装,因此数字值可以调用Number.prototype中的方法。例如,tofixed(..)方法可指定小数部分的显示位数:
// 无效语法:
42.toFixed( 3 ); // SyntaxError
// 下面的语法都有效:
a = (42).toFixed(3); // "42.000"
b = 0.42.toFixed(3); // "0.420"
c = 42..toFixed(3); // "42.000"
d = 42 .toFixed(3); // "42.000"
2)整数检测
//整数检测
if (!Number.isInteger) {
Number.isInteger = function(num) {
return typeof num == "number" && num % 1 == 0;
};
}
//安全整数检测
if (!Number.isSafeInteger) {
Number.isSafeInteger = function(num) {
return Number.isInteger(num) &&
Math.abs(num) <= Number.MAX_SAFE_INTEGER;
};
}
3)null与undefined
特殊数值undefined与null。它们的名称既是类型也是值。
null指空值(empty value),曾赋过值,但是目前没有值。null是一个特殊关键字,不是标识符,我们不能将其当作变量来使用和赋值。
undefined指没有值(missing value),从未赋值。undefined是一个标识符,可以被当作变量来使用和赋值。
//将undefined当作变量来使用和赋值
function foo() {
"use strict";
var undefined = 2;
console.log(undefined); //
}
foo();
4)不是数字的数字
NaN意指“不是一个数字”(not a number),将它理解为“无效数值”、“失败数值”或者“坏数值”可能更准确些。
NaN是一个特殊值,它和自身不相等,是唯一一个非自反(自反,即x === x不成立)的值。而NaN != NaN为true。
var a = 2 / "foo"; // NaN
typeof a === "number"; // true
if (!Number.isNaN) {
Number.isNaN = function(n) { //非数字类型的值在isNaN中也会返回true
return (
typeof n === "number" &&
window.isNaN(n)
);
};
}
//利用NaN不等于自身这个特点
if (!Number.isNaN) {
Number.isNaN = function(n) {
return n !== n;
};
}
5)零值
加法和减法运算不会得到负零(negative zero)。负零在开发调试控制台中通常显示为“-0”,但在一些老版本的浏览器中仍然会显示为“0”。
//零值
a = 0 / -3; // -0
b = 0 * -3; // -0
c = +"-0"; // -0
d = Number("-0"); // -0
e = JSON.parse("-0"); // -0
//值比较
-0 == 0; // true
-0 === 0; // true
0 > -0; // false
//-0的判断方式
function isNegZero(n) {
n = Number(n);
return (n === 0) && (1 / n === -Infinity);
}
isNegZero(-0); // true
isNegZero(0 / -3); // true
isNegZero(0); // false
6)特殊等式
NaN和-0在相等比较时的表现有些特别。
由于NaN和自身不相等,所以必须使用ES6中的Number.isNaN(..)。 而-0等于0(对于===也是如此),因此我们必须使用isNegZero(..)这样的工具函数。
//特殊等式
if (!Object.is) {
Object.is = function(v1, v2) {
// 判断是否是-0
if (v1 === 0 && v2 === 0) {
return 1 / v1 === 1 / v2;
}
// 判断是否是NaN
if (v1 !== v1) {
return v2 !== v2;
}
// 其他情况
return v1 === v2;
};
}
7)值和引用
JavaScript引用指向的是值。如果一个值有10个引用,这些引用指向的都是同一个值,它们相互之间没有引用/指向关系。
向函数传递值的时候,实际是将引用值的一个复本传递进去,不管是基本类型还是对象。
//基本类型
var a = 2;
var b = a; // b是a的值的一个副本
b++;
a; //
b; // //变量引用同一个值
var c = [1, 2, 3];
var d = c; // d是[1,2,3]的一个引用
d.push(4);
c; // [1,2,3,4]
d; // [1,2,3,4] //变量引用不同的值
var a = [1, 2, 3];
var b = a;
b = [4, 5, 6]; //给b重新赋值,引用新的值,不影响a的引用
a; // [1,2,3]
b; // [4,5,6] //函数内让参数重新引用值
function foo2(x) {
x.push(4);
x; // [1,2,3,4] x = [4, 5, 6];// 然后重新引用新的值
x.push(7);
x; // [4,5,6,7]
}
var a = [1, 2, 3];
//向函数传递a的时候,实际是将引用a的一个复本赋值给x,而a仍然指向[1,2,3]
foo2(a);
a; // 是[1,2,3,4],不是[4,5,6,7]
上面的源码可以在此次浏览。
二、原生函数
常用的原生函数有:String()、Number()、Boolean()、Array()、Object()、Function()、RegExp()、Date()、Error()、Symbol()。
1)内部属性[[Class]]
这个属性无法直接访问,一般通过Object.prototype.toString(..)来查看。
//内部属性[[Class]]
Object.prototype.toString.call([1, 2, 3]); // "[object Array]"
Object.prototype.toString.call(/regex-literal/i); // "[object RegExp]"
//基本类型
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
虽然Null()和Undefined()这样的原生构造函数并不存在,但是内部[[Class]]属性值仍然是"Null"和"Undefined"。
基本类型值被各自的封装对象自动包装,所以它们的内部[[Class]]属性值分别为"String"、"Number"和"Boolean"。
Object.prototype.toString.call("abc"); // "[object String]"
Object.prototype.toString.call(42); // "[object Number]"
Object.prototype.toString.call(true); // "[object Boolean]"
2)封装对象包装
由于基本类型值没有.length和.toString()这样的属性和方法,需要通过封装对象才能访问,此时JavaScript会自动为基本类型值包装(box或者wrap)一个封装对象:
//封装对象
var a = "abc";
a.length; //
a.toUpperCase(); // "ABC"
如果想要自行封装基本类型值,可以使用 Object(..) 函数(不带 new 关键字)
//自行封装基本类型
var a = "abc";
var b = new String(a);
var c = Object(a); typeof a; // "string"
typeof b; // "object"
typeof c; // "object"
b instanceof String; // true
c instanceof String; // true
Object.prototype.toString.call(b); // "[object String]"
Object.prototype.toString.call( c ); // "[object String]"
3)拆封
如果想要得到封装对象中的基本类型值,可以使用valueOf()函数:
//拆封
var a = new String("abc");
var b = new Number(42);
var c = new Boolean(true); console.log(a.valueOf()); // "abc"
console.log(b.valueOf()); //
console.log(c.valueOf()); // true
在需要用到封装对象中的基本类型值的地方会发生隐式拆封。
上面的源码可以在此处浏览。
《你不知道的JavaScript》整理(五)——值与原生函数的更多相关文章
- 你不知道的JavaScript(五)内置对象模版
尽管JavaScript中有对象的概念,但一般我们并不说JavaScript是面向对象的编程语言,因为它不具备面向对象的一些最基本特征. 在c++/Java等这些面向对象的编程语言中,我们要定义一个对 ...
- 《你不知道的JavaScript(上)》笔记——函数作用域和块作用域
关于函数声明:如果 function 是声明中的第一个词, 那么就是一个函数声明, 否则就是一个函数表达式.例如匿名函数这种形式,函数会被当作函数表达式而不是一个标准的函数声明来处理. (functi ...
- 《你不知道的JavaScript》整理(一)——作用域、提升与闭包
最近在读一本进阶的JavaScript的书<你不知道的JavaScript(上卷)>,里面分析了很多基础性的概念. 可以更全面深入的理解JavaScript深层面的知识点. 一.函数作用域 ...
- 《你不知道的JavaScript》整理(二)——this
最近在读一本进阶的JavaScript的书<你不知道的JavaScript(上卷)>,这次研究了一下“this”. 当一个函数被调用时,会创建一个活动记录(执行上下文). 这个记录会包含函 ...
- javascript函数一共可分为五类: ·常规函数 ·数组函数 ·日期函数 ·数学函数 ·字符串函数
javascript函数一共可分为五类: ·常规函数 ·数组函数 ·日期函数 ·数学函数 ·字符串函数 1.常规函数 javascript常规函数包括以下9个 ...
- JavaScript(五):函数(闭包,eval)
1.函数的申明:三种方法: function命令 函数表达式:变量赋值 Function构造函数 //method 1: function命令 function test(){ console.log ...
- 精读JavaScript模式(五),函数的回调、闭包与重写模式
一.前言 今天地铁上,看到很多拖着行李箱的路人,想回家了. 在上篇博客结尾,记录到了函数的几种创建方式,简单说了下创建差异,以及不同浏览器对于name属性的支持,这篇博客将从第四章函数的回调模式说起. ...
- JavaScript 基础(五) 函数 变量和作用域
函数定义和调用 定义函数,在JavaScript中,定义函数的方式如下: function abs(x){ if(x >=0){ return x; }else{ return -x; } } ...
- JavaScript原生函数(内置函数)
1.JavaScript原生函数(内置函数) JavaScript原生函数(内置函数)有: String() Number() Boolean() Array() Object() Function( ...
随机推荐
- iOS 程序初始一个带导航栏的视图
@synthesize window = _window; @synthesize rootViewController = _rootViewController; - (BOOL)applicat ...
- 浅谈tomcat的配置及数据库连接池的配置
1.如何修改tomcat的端口 在某些情况下,可能需要修改tomcat监听的端口8080,比如: a.需要启动两份tomcat服务器 b.某个服务占用了8080端口(1433,1521,3306... ...
- mysql 常用技巧
1.正则使用 比 LIKE 会牺牲很多的系统资源 尽量不要用 正则的语法和JS PHP 差不多 select * from t1 where email REGEXP "@163[,.]co ...
- 阿里云服务器windows系统C盘一键清理脚本
@ECHO OFF @echo @echo @echo 清理几个比较多垃圾文件的地方 DEL /F /S /Q "C:\WINDOWS\PCHealth\ERRORREP\QSIGNOFF\ ...
- 你真的懂ajax吗?
前言 总括: 本文讲解了ajax的历史,工作原理以及优缺点,对XMLHttpRequest对象进行了详细的讲解,并使用原生js实现了一个ajax对象以方便日常开始使用. damonare的ajax库: ...
- oracle数据库包package小例子
为了把某一个模块的函数.存储过程等方便查询维护,可以把它们打到一个包里.下面给出一个简单的小例子. 1.创建包头 create or replace package chen_pack is func ...
- Git学习之路(2)-安装GIt和创建版本库
▓▓▓▓▓▓ 大致介绍 前面一片博客介绍了Git到底是什么东西,如果有不明白的可以移步 Git学习之路(1)-Git简介 ,这篇博客主要讲解在Windows上安装Git和创建一个版本库 ▓▓▓▓▓▓ ...
- 源码(07) -- java.util.Iterator<E>
java.util.Iterator<E> 源码分析(JDK1.7) ----------------------------------------------------------- ...
- 简述jpg、gif、png-8、png-24的区别,分别使用场景
gif.jpg.png格式的图片在网站制作中的区别 Gif 格式特点: 1.透明性:gif是一种布尔透明类型,即它可以使全透明,也可是全不透明,但是它并没有半透明的(alpha透明). 2.动画:gi ...
- HashSet、LinkedHashSet、TreeSet使用区别
HashSet:哈希表是通过使用称为散列法的机制来存储信息的,元素并没有以某种特定顺序来存放: LinkedHashSet:以元素插入的顺序来维护集合的链接表,允许以插入的顺序在集合中迭代: Tree ...