接触写博客有一段时间了,都是边学边学着写,但总感受写的凌乱,想起啥写啥。这几天在刷红宝书,收获仍是蛮多的,决定结合本身的学习,写一个系列,我叫它「前端料包」,旨在巩固前端基础,努力提高本身,同时也乐于作一个分享者。这个系列包括但不限于下面脑图中的内容,目录和发文顺序暂且以下:html
在讲数据类型以前,想先讲讲变量。 JavaScript
的变量是松散型的,便可以保存任何类型的数据,在JavaScript中咱们使用var关键字来声明一个变量(es6中新增了let 、 const 来声明变量)前端
var message1 = 10;
var message2 = true;
var message3 = "hello world";
复制代码
固然,由于松散型,也能够改变同一变量的值的类型,虽然不推荐这么作,可是在JavaScript中彻底有效。es6
var message1 = 10;
message1 = true;// 从新给变量message赋不一样类型的值,数据类型也会随之改变,不推荐这样作
复制代码
而咱们全部数据类型的值都是保存在自定义的某一个变量中。 JavaScript
从诞生到如今最新的正式版本,一共有7种数据类型,其中有6种基本数据类型:Undefined、Null、Boolean、Number、String和Symbol(es6新增)
;1种引用数据类型——Object
(Object
本质上是由一组无序的名值对组成的)。JavaScript
不支持任何建立自定义类型的机制,而全部值最终都将是上述 7 种数据类型之一。这里要特别说明一下,最新的基本数据类型的第7个兄弟——BigInt
已经诞生,将在下一版本(es10)中做为新特性出现(V8引擎v6.7 默认启用对 BigInt
的支持)。segmentfault
BigInt
是什么?BigInt
是JavaScript
中一种能够用来表示任意精度整数的基本数据类型数组
BigInt
能够用来表示任意精度整数的特性为JavaScript
解锁了更多的骚操做,使用BigInt
能够告别过去由于整数运算致使溢出的痛苦。特别是金融方面由于涉及大量的数据运算,好比高精度时间戳,或者数值过大的ID,这些是没法安全的用Number类型去存储的,因此退而求其次使用String类型去存储,有了BigInt类型后就能够安全的将其存储为数值类型。浏览器另外
BigInt
的实现也为实现BigDecimal
打下坚实基础,那将对于以十进制精度表示货币金额并对其进行精确运算(也就是0.10 + 0.20 !== 0.30问题)很是有帮助安全
关于BigInt
能够看看这篇文章:JavaScript基本类型之--BigIntapp
Undefined
类型只有一个值,即特殊的undefined
,一个变量在声明后未初始化时,这个变量的值就是undefined
。函数
var message;
alert(message);// undefined
复制代码
须要注意的是声明了但未初始化的变量与未声明的变量是不同的性能
var msg;
alert(msg);// 声明了未初始化(即赋值),默认值为"undefined"
alert(a);// 报错
复制代码
但使用typeof
操做符来检测上面两个变量时,都会返回undefined
var msg;
// var a
alert(typeof msg);// "undefined"
alert( typeof a);// "undefined"
复制代码
这个结果有其逻辑上的合理性。由于虽然这两种变量从技术角度看有本质区别,但实际上不管对哪一种变量也不可能执行真正的操做。
未初始化的变量会自动被赋予 undefined 值,没有必要将变量显式的设置为
undefined
,但显式地初始化变量依然是明智的选择。若是可以作到这一点,那么当typeof
操做符返回"undefined"值时,咱们就知道被检测的变量尚未被声明,而不是还没有初始化。
Null
类型是第二个只有一个值的数据类型,这个特殊的值是 null
。null
值表示一个空对象指针,使用 typeof
操做符检测 null 值时会返回"object"
。
var jake = null;
alert(typeof jake ); // "object"
复制代码
虽然 typeof null
会输出 object
,但这只是 JS
存在的一个悠久 Bug
。在 JS
的最第一版本中使用的是 32 位系统,为了性能考虑使用低位存储变量的类型信息,000 开头表明是对象然而 null
表示为全零,因此将它错误的判断为 object
。 null
值的主要做用是若是定义的变量在未来用于保存对象,那么最好将该变量初始化为null
值。
Boolean
类型是JavaScript
中使用最多的一种基本数据类型,只有两个值true
和false
(全为小写)。
var a = true;
var b = false;
复制代码
虽然Boolean
类型只有两个值,但JavaScript
中全部类型的值都有与这两个Boolean
值等价的值,能够调用转型函数Boolean()
将其余类型的值转化为Boolean
值。
var msg = "hello world";
var magBoolean = Boolean(msg);
复制代码
根据转换值的数据类型及其实际值,返回一个Boolean
值。各类数据类型及其对应的转换规则以下表:
数据类型 | 转为true | 转为false |
---|---|---|
Boolean | true | false |
String | 任何非空字符串 | " "(空字符串) |
Number | 任何非零数字(包括无穷大) | 0和NaN |
Object | 任何对象 | null |
Undefined | not applicable(不适用) | undefined |
Number
类型算是JavaScript
中最复杂也最使人关注的基本数据类型了,Number
能够同时表示整数和浮点数值,同时也支持各类进制和科学计数法。具体以下
var intNum = 55; // 整数
// 浮点数
var floatNum1 = 1.1;
var floatNum2 = 0.1;
var floatNum3 = .1; // 有效,但不推荐
// 科学计数法
var floatNum = 3.125e7; // 等于 31250000 至关于 3.125*10的7次方
// 八进制(以O开头),数字序列(0~7)
var octalNum1 = 070; // 八进制的 56
var octalNum2 = 079; // 无效的八进制数值——解析为 79
var octalNum3 = 08; // 无效的八进制数值——解析为 8
// 十六进制(以Ox开头),数字序列(0~9及A~F),字母大小写同等
var hexNum1 = 0xA; // 十六进制的 10
var hexNum2 = 0x1f; // 十六进制的 31
复制代码
JavaScript
可以表示的最小数值保存在 Number.MIN_VALUE
中——在大多数浏览器中,这个值是 5e-324
;可以表示的最大数值保存在Number.MAX_VALUE
中——在大多数浏览器中,这个值是 1.7976931348623157e+308
。若是某次计算的结果获得了一个超出 JavaScript
数值范围的值,那么这个数值将被自动转换成特殊的 Infinity
值(有正负)。 这里要特别说明一下,浮点数值的最高精度是 17 位小数,但在进行算术计算时其精确度远远不如整数。例如,0.1 + 0.2的结果不是 0.3,而是 0.30000000000000004。这是由于0.1和0.2在转换成二进制后会无限循环,因为标准位数的限制后面多余的位数会被截掉,此时就已经出现了精度的损失,相加后因浮点数小数位的限制而截断的二进制数字在转换为十进制就会变成0000000000000004。因此上面提到的BigInt就应运而生。
关于浮点数值计算会产生舍入偏差的问题,有一点须要明确:这是使用基于IEEE754 数值的浮点计算的通病,ECMAScript 并不是独此一家;其余使用相同数值格式的语言也存在这个问题。
NaN(Not a Number)
,即非数值,用于表示一个原本要返回数值的操做数未返回数值的状况。 NaN
有两个非同寻常的特色:
NaN
的操做(例如NaN/10
)都会返回NaN
;NaN
与任何值都不相等,包括NaN
自己。针对这两个特色,JavaScript
定义了isNaN()
函数。这个函数接受一个参数,该参数能够是任何类型。isNaN()
在接收到一个值后,会尝试将这个值转换为数值,而任何不能被转换为数值的值都会致使函数返回true
。
alert(isNaN(NaN)); //true
alert(isNaN(10)); //false(10 是一个数值)
alert(isNaN("10")); //false(能够被转换成数值 10)
alert(isNaN("blue")); //true(不能转换成数值)
alert(isNaN(true)); //false(能够被转换成数值 1)
复制代码
JavaScript
提供3个函数能够把非数值转换为数值:
Number()
能够用于任何数据类型parseInt()
和parseFloat()
专门用于把字符串转换为数值Number() Number()
函数的转换规则不少,这里直接引用红宝书里的描述:
若是是 Boolean 值,true 和 false 将分别被转换为 1 和 0。
若是是数字值,只是简单的传入和返回。
若是是 null 值,返回 0。 若是是 undefined,返回 NaN。
若是是字符串,遵循下列规则:
a、中只包含数字(包括前面带正号或负号的状况),则将其转换为十进制数值,即"1" 会变成 1,"123"会变成 123,而"011"会变成 11(注意:前导的零被忽略了);
b、串中包含有效的浮点格式,如"1.1",则将其转换为对应的浮点数值(一样,也会忽 略前导零);
c、字符串中包含有效的十六进制格式,例如"0xf",则将其转换为相同大小的十进制整 数值;
d、字符串是空的(不包含任何字符),则将其转换为 0; 若是字符串中包含除上述格式以外的字符,则将其转换为 NaN。
若是是对象,则调用对象的 valueOf()方法,而后依照前面的规则转换返回的值。若是转换 的结果是 NaN,则调用对象的 toString()方法,而后再次依照前面的规则转换返回的字符 串值。
var num1 = Number("Hello world!"); //NaN
var num2 = Number(""); //0
var num3 = Number("000011"); //11
var num4 = Number(true); //1
NumberExample04.htm
复制代码
parseInt() parseInt()
函数在转换字符串时,更多的是看其是否符合数值模式。它会忽略字 符串前面的空格,直至找到第一个非空格字符。若是第一个字符不是数字字符或者负号,parseInt()
就会返回 NaN
;也就是说,用 parseInt()
转换空字符串会返回 NaN
(Number()
对空字符返回 0
)。如 果第一个字符是数字字符,parseInt()
会继续解析第二个字符,直到解析完全部后续字符或者遇到了 一个非数字字符。
var num1 = parseInt("1234blue"); // 1234
var num2 = parseInt(""); // NaN
var num3 = parseInt("0xA"); // 10(十六进制数)
var num4 = parseInt(22.5); // 22
var num5 = parseInt("070"); // 56(八进制数)
var num6 = parseInt("70"); // 70(十进制数)
var num7 = parseInt("0xf"); // 15(十六进制数)
复制代码
在使用 parseInt()
解析像八进制字面量的字符串时,ECMAScript 3
和 5
存在分歧。
//ECMAScript 3 认为是 56(八进制),ECMAScript 5 认为是 70(十进制)
var num = parseInt("070");
复制代码
所以parseInt()
引入第二个参数:转换时使用的基数,以解决上述困惑。
var num1 = parseInt("10", 2); //2 (按二进制解析)
var num2 = parseInt("10", 8); //8 (按八进制解析)
var num3 = parseInt("10", 10); //10 (按十进制解析)
var num4 = parseInt("10", 16); //16 (按十六进制解析)
复制代码
parseFloat() 与 parseInt()
函数相似,parseFloat()
也是从第一个字符(位置 0)开始解析每一个字符。并且也是一直解析到字符串末尾,或者解析到碰见一个无效的浮点数字字符为止。
var num1 = parseFloat("1234blue"); //1234 (整数)
var num2 = parseFloat("0xA"); //0
var num3 = parseFloat("22.5"); //22.5
var num4 = parseFloat("22.34.5"); //22.34 第二个小数点无效
var num5 = parseFloat("0908.5"); //908.5
var num6 = parseFloat("3.125e7"); //31250000
复制代码
String
,即字符串,由一对双引号或单引号表示(单双引号没有区别)
var firstName = "Jake";
var lastName = 'JakeZhang';
复制代码
JavaScript
中的字符串是不可变的,也就是说,字符串一旦建立,它们的值就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,而后再用另外一个包含新值的字符串填充该变量。
var name = "Jake";
name = name + "Zhang";
复制代码
实现这个操做的过程以下:首先建立一个能容纳 10 个字符的新字符串,而后在这个字符串中填充"Jake"和"Zhang",最后一步是销毁原来的字符串"Jake"和字符串"Zhang",由于这两个字符串已经没用了(这个过程是在后台发生的)。
实际开发中常常为方便存储,常常须要将值转换为字符串。要把一个值转换为一个字符串有两种方式:
一、toString() 除了null
和undefined
值没有tostring()
方法,其余值都有这个方法,该方法返回字符串的一个副本。
var age = 11;
var ageAsString = age.toString(); // 字符串"11"
var found = true;
var foundAsString = found.toString(); // 字符串"true"
复制代码
toString()
能够传入一个参数:输出数值的基数。能够输出以二进制、八进制、十六进制,乃至其余任意有效进制格式表示的字符串值。下面给出几个例子:
var num = 10;
alert(num.toString()); // "10"
alert(num.toString(2)); // "1010"
alert(num.toString(8)); // "12"
alert(num.toString(10)); // "10"
alert(num.toString(16)); // "a"
复制代码
二、使用+" " 便可以经过要转换的值 + 空字符串(" "),也能够实现转换。
var num = 10;
var numAsString = num + " ";// "10"
var boolean = true;
var booleanAsString = boolean + " ";// "true"
var a ;
var b = a + " ";// "undefined "
var c = null;
var d = c + " ";// "null "
var o = {
valueOf: function() {
return -1;
}
}
var m = o + " ";// "-1 "
复制代码
Symbol
是es6
新增的一种原始数据类型,表示独一无二的值,是一种惟一标识符。Symbol
值经过Symbol()
函数生成。
let id = Symbol("jake");
复制代码
Symbol
的主要特色是如上所说的惟一性,可用做对象的惟一属性名,即便是用同一个变量生成的值也不相等。
let id1 = Symbol('jake');
let id2 = Symbol('jake');
console.log(id1 == id2); //false
复制代码
但咱们不排除但愿可以屡次使用同一个symbol
值的状况。官方提供的Symbol.for()
方法能够作到这一点。它接受一个字符串做为参数,而后搜索有没有以该参数做为名称的 Symbol
值。若是有,就返回这个 Symbol
值,不然就新建一个以该字符串为名称的 Symbol
值,并将其注册到全局。
let name1 = Symbol.for('name'); //检测到未建立后新建
let name2 = Symbol.for('name'); //检测到已建立后返回
console.log(name1 === name2); // true
复制代码
Symbol
的另外一特色是隐藏性,Symbol
做为属性名,遍历对象的时候,该属性不会出如今for...in、for...of
循环中,也不会被Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回。
let id = Symbol("id");
let obj = {
[id]:'symbol'
};
for(let option in obj){
console.log(obj[option]); //空
}
复制代码
可是也有可以访问的方法:Object.getOwnPropertySymbols
该方法会返回一个数组,成员是当前对象的全部用做属性名的Symbol
值。
let id = Symbol("id");
let obj = {
[id]:'symbol'
};
let array = Object.getOwnPropertySymbols(obj);
console.log(array); //[Symbol(id)]
console.log(obj[array[0]]); //'symbol'
复制代码
关于Symbol
这个新的数据类型更多的知识点能够参考阮神的文章—>传送门
Object
类型是JavaScript
中最庞大而复杂的引用数据类型,本文只作简单介绍,后续的文章会作Object
的详细介绍。 Object
,即对象,是一组数据和功能的集合。对象能够经过执行new
操做符后跟要建立 的对象类型的名称来建立。而建立 Object
类型的实例并为其添加属性和(或)方法,就能够建立自定 义对象。
var person1 = new Object();
person.name = "Jake";
person.age = 23;
var person2 = {}; //与 new Object()相同
person2.name = "Jake";
perso2.age = 23;
//字面量的建立方式
var person3 = {
name:"jakezhang",//name若是是保留字、有链接符/空格,则要'name-p',即便用字符串
age:23,
action:function(){
console.log(this.name);
}
};
复制代码
以上任意一种方式均可以建立一个对象实例,固然更多的写法和设计思想之后的文章再作体现。在实际的开发中咱们用的最多的是字面量的方式,由于这种语法要求的代码量少,并且可以给人封装数据的感受。这里引用一个红宝书的例子:
function displayInfo(args) {
var output = "";
if (typeof args.name == "string"){
output += "Name: " + args.name + "\n";
}
if (typeof args.age == "number") {
output += "Age: " + args.age + "\n";
}
alert(output);
}
displayInfo({
name: "Nicholas",
age: 29
});
displayInfo({
name: "Greg"
});
复制代码
代码相信都看得懂~
Object 的每一个实例都具备下列属性和方法:
constructor
:保存着用于建立当前对象的函数。对于前面的例子而言,构造函数(constructor
)就是 Object()
。
hasOwnProperty(propertyName)
:用于检查给定的属性在当前对象实例中(而不是在实例的原型中)是否存在。其中,做为参数的属性名(propertyName
)必须以字符串形式指定(例如:o.hasOwnProperty("name")
)。
isPrototypeOf(object)
:用于检查传入的对象是不是传入对象的原型。
propertyIsEnumerable(propertyName
):用于检查给定的属性是否可以使用 for-in 语句来枚举。与hasOwnProperty()
方法同样,做为参数的属性名必须以字符串形式指定。
toLocaleString()
:返回对象的字符串表示,该字符串与执行环境的地区对应。
toString()
:返回对象的字符串表示。
valueOf()
:返回对象的字符串、数值或布尔值表示。一般与 toString()方法的返回值相同。
因为在 ECMAScript 中 Object 是全部对象的基础,所以全部对象都具备这些基本的属性和方法。
var name = "Jake Zhang";
name.toUpperCase();//输出 JAKE ZHANG
console.log(name);// 输出 Jake Zhang
复制代码
由以上代码可看出基本数据类型的值是不可变的。
stack
)中存储。var n = 1;
var m = true;
console.log(n == m);//true
console.log(n === m);// false
复制代码
"==":只进行值的比较,会进行数据类型转换;
"===":不会转换数据类型。
var person = {
name:'jake',
age:22,
action:function () {
console.log("do something!")
}
}
person.age = 23;
console.log(person.age)// 23
复制代码
有上面的代码可看出引用数据 类型能够拥有一个或多个属性和方法,并且是能够动态修改的。
var person1 = {
age:20
}
var person2 = person1;
person2.age = 23;
console.log(person1.age = person2.age)// true
复制代码
前面讲到基本数据类型和引用数据类型存储于内存中的位置不同,引用数据类型存储在堆中的对象,与此同时,在栈中存储了指针,而这个指针的指向正是堆中实体的起始位置。变量person1初始化时,person1指针指向该对象{age:20}的地址,将person1赋给person2后,person2又指向该对象{age:20}的地址,这两个变量指向了同一个对象。所以改变其中任何一个变量,都会相互影响。
var a = {age:22}
var b = a;
a = 1;
console.log(b);//{age:22}
复制代码
上面代码中,a和b指向同一个对象,而后a的值变为1,这时不会对b产生影响,b仍是指向原来的那个对象。
小生乃前端小白一枚,写文章的最初衷是做学习笔记,为了让本身对该知识点有更深入的印象和理解,写的东西也很小白,文中若有不对,欢迎指正~ 而后就是但愿看完的朋友点个喜欢,也能够关注一波~ 我会持续输出!