最新的 ECMAScript 标准定义了 7 种数据类型:javascript
Undefined类型只有一个值undefined
,表示"缺乏值",就是此处应该有一个值,可是尚未定义。主要的用法:html
(1)变量被声明了,但没有赋值时,就等于undefined。
(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
PS: 值 undefined 并不一样于未定义的值。可是,typeof 运算符并不真正区分这两种值。
var i; console.log(i) ; // undefined function f(x){console.log(x)} f(); // undefined var o = new Object(); console.log(o.p); // undefined var func = f(); console.log(func); // undefined console.log(typeof y); //"undefined"
null类型的默认值是null
,从逻辑角度讲,是表示一个空对象指针,表示"没有对象",即该处不该该有值。主要用法:java
(1) 做为函数的参数,表示该函数的参数不是对象。
(2) 做为对象原型链的终点。
Object.getPrototypeOf(Object.prototype) // null
区别undefined:git
当一个变量声明后,未初始化,则该值为undefined,若是这个值是为了保存对象,则修改其默认初始化的值,改成null。 因此当检测其类型时,会显示类型为object。
typeof null // object (历史缘由,不是'null') typeof undefined // "undefined" null === undefined // false null == undefined // true null === null // true null == null // true !null // true Number(null) // 0 Number(undefined) // NaN isNaN(1 + null) // false isNaN(1 + undefined) // true
布尔类型,该类型有两个值:true
false
。Bloolean()函数,能够将其余类型的值转换为布尔类型。同时也存在隐式类型转换。es6
这里区分一下Truthy类型和Falsy类型值。
Falsy类型值包括:""
,0
,null
,undefined
,NaN
,false
。
除了Falsy类型值之外的都被称为Truthy类型值,它们会被转换为true
。
Boolean(null) // false Boolean('hello') // true Boolean('0') // true Boolean(' ') // true Boolean([]) // true Boolean(function(){}) // true
根据 ECMAScript 标准,JavaScript 中只有一种数字类型:基于 IEEE 754 标准的双精度 64 位二进制格式的值(-(263 -1) 到 263 -1)。它并无为整数给出一种特定的类型。除了可以表示浮点数外,还有一些带符号的值:+Infinity,-Infinity 和 NaN (非数值,Not-a-Number)。
整数能够用十进制(基数为10)、十六进制(基数为16)、八进制(基数为8)以及二进制(基数为2)的字面值来表示。json
0, 117 and -345 (十进制, 基数为10) 015, 0001 and -0o77 (八进制, 基数为8) 0x1123, 0x00111 and -0xF1A7 (十六进制, 基数为16或"hex") 0b11, 0b0011 and -0b11 (二进制, 基数为2)
浮点数(有趣的一点是,在计算前其存储为字符串)所占据的内存空间是整数的两倍。
语法:[(+|-)][digits][.digits][(E|e)[(+|-)]digits]
segmentfault
3.14 -.2345789 // -0.23456789 -3.12e+12 // -3.12*1012 .1e-23 // 0.1*10-23=10-24=1e-24
NaN:
一、即非数值,是一个特殊的值,这个数值用于表示一个原本要返回数值的操做数,未返回数值的状况。好比任何数值除以0,本是不符合规范的,js里,这样的操做返回NaN
(可是实际上,只有0除以0时返回NaN
,其余则无穷值)。数组
二、NaN
有两个不一样寻常的特色:任何涉及NaN
的操做都会返回NaN
,NaN
值与任何值都不相等,包括自己。
三、isNaN()
函数,这个函数能够判断,传递的参数是否“不是数值”这里涉及数值转换的问题,例如“10”
这个字符串就能够转换为10
,可是“blue”
这个字符串则没法转换为数字,因此isNaN("blue")==true
。安全
+0 === -0 //true 42 / +0; // Infinity 42 / -0; // -Infinity NaN == NaN //false
+Infinity,-Infinity:
要检查值是否大于或小于 +/-Infinity
,你可使用常量 Number.MAX_VALUE
和 Number.MIN_VALUE
。另外在 ECMAScript 6 中,你也能够经过 Number.isSafeInteger()
方法还有 Number.MAX_SAFE_INTEGER 和 Number.MIN_SAFE_INTEGER
来检查值是否在双精度浮点数的取值范围内。 超出这个范围,JavaScript 中的数字再也不安全了,也就是只有 second mathematical interger 能够在 JavaScript 数字类型中正确表现。app
这个算是比较熟悉的了这里引用一下MDN的描述。
JavaScript的字符串类型用于表示文本数据。它是一组16位的无符号整数值的“元素”。在字符串中的每一个元素占据了字符串的位置。第一个元素的索引为0,下一个是索引1,依此类推。字符串的长度是它的元素的数量。
不一样于类 C 语言,JavaScript 字符串是不可更改的。这意味着字符串一旦被建立,就不能被修改。可是,能够基于对原始字符串的操做来建立新的字符串。
主要强调一下ES2015的模板字符串:
// Basic literal string creation `In JavaScript '\n' is a line-feed.` // Multiline strings `In JavaScript this is not legal.` // String interpolation var name = "Bob", time = "today"; `Hello ${name}, how are you ${time}?` // Construct an HTTP request prefix is used to interpret the replacements and construction POST`http://foo.org/bar?a=${a}&b=${b} Content-Type: application/json X-Credentials: ${credentials} { "foo": ${foo}, "bar": ${bar}}`(myOnReadyStateChangeHandler);
String()
函数能够将任何类型的值转换为字符串,包括null
转换为'null'
、undefined
转换为'undefined'
。
语法:Symbol([description])
一、每一个从Symbol()返回的symbol值都是惟一的。
直接使用Symbol()建立新的symbol类型,并用一个字符串(可省略)做为其描述。如下代码建立了三个新的symbol类型。 字符串 “foo” 的做用仅为描述,它每次都会建立一个新的 symbol类型:
var sym1 = Symbol(); var sym2 = Symbol('foo'); var sym3 = Symbol('foo'); Symbol("foo") === Symbol("foo"); // false
还可使用Symbol.for
方法建立新的symbol类型,和前者区别Symbol.for()
会把symbol值以一个key值登记到全局环境中,Symbol()
就不会。Symbol.for()
不会每次调用就返回一个新的 Symbol 类型的值,而是会先检查给定的key是否已经存在,若是不存在才会新建一个值。好比,若是你调用Symbol.for("cat")
30 次,每次都会返回同一个 Symbol 值,可是调用Symbol("cat")
30 次,会返回 30 个不一样的 Symbol 值。查看登记的Symbol值可使用Symbol.keyFor
方法,该方法返回一个已登记的 Symbol 类型值的key。
let sym1 = Symbol('foo'); let sym2 = Symbol('foo'); let sym3 = Symbol.for('foo'); let sym4 = Symbol.for('foo'); sym1 === sym2 //false sym3 === sym4 //true Symbol.keyFor(sym1) //undefined Symbol.keyFor(sym3) //"foo"
二、 再也不支持new 运算符的语法:
var sym = new Symbol(); // TypeError
这会阻止建立一个显式的 Symbol 包装器对象而不是一个 Symbol 值。围绕原始数据类型建立一个显式包装器对象从 ECMAScript 6 开始再也不被支持。 然而,现有的原始包装器对象,如 new Boolean、new String以及new Number由于遗留缘由仍可被建立。
三、特殊的类型转换
Symbol 值不能与其余类型的值进行运算。
Symbol 值能够显式转为字符串、布尔值,可是不能转为数值。
四、用于对象属性名(主要)
Symbol 值做为对象属性名时,不能用点运算符。通常经过方括号结构和Object.defineProperty
,将对象的属性名指定为一个 Symbol 值。
let sym1 = Symbol(); let sym2 = Symbol(); let sym3 = Symbol(); let a = { [sym1]: 'Symbol1'; }; a[sym2] = 'Symbol2'; Object.defineProperty(a, sym3, { value: 'Symbol3' }); a.sym1 = 'Hello!'; a[sym1] // "Symbol1" a['sym1'] // "Hello!"
Symbol 做为属性名,该属性不会出如今for...in
、for...of
循环中,也不会被Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回。可是,它也不是私有属性,有一个Object.getOwnPropertySymbols
方法,返回一个数组,成员是当前对象的全部用做属性名的 Symbol 值。
更多的Symbol相关内容参考这篇文章—— 传送门
在计算机科学中, 对象是指内存中的能够被标识符引用的一块区域。
对象属于复杂数据类型,也能够说是引用类型(逻辑上等价于class/类)。相对于原始数据类型的直接存取(栈内存),复杂数据类型的存储方式为引用(堆内存,栈内存保存对应的指针)。
ECMAScript 中的全部对象都由这个对象继承而来,Object 对象中的全部属性和方法都会出如今其余对象中,因此理解了 Object 对象,就能够更好地理解其余对象。
本文主要介绍如下几点:
一、Object()与new Object()
Object函数能够把任意值转换为对象;new Object()
则是生成新对象,能够简写为{}
。除语义上的不一样外,二者的用法相同,如下以Object()
为例:
var obj = Object(); var obj = Object(undefined); var obj = Object(null); //以上语句等效,返回空对象 obj instanceof Object // true var obj = Object(1); obj instanceof Object // true obj instanceof Number // true var obj = Object('foo'); obj instanceof Object // true obj instanceof String // true var obj = Object(true); obj instanceof Object // true obj instanceof Boolean // true
若是参数原本就是一个对象便不须要转换,直接返回该对象:
var arr = []; var obj = Object(arr); // 返回原数组 obj === arr // true var value = {}; var obj = Object(value) // 返回原对象 obj === value // true var fn = function () {}; var obj = Object(fn); // 返回原函数 obj === fn // true
二、Object静态方法
所谓“静态方法”,是指部署在Object对象自身的方法。例如:Object.key = value
、{key:value}
。
通常使用Object.keys
方法和Object.getOwnPropertyNames
方法来遍历对象的属性。区别在于后者能够列举不可枚举的属性名,例如数组的length
。
var a = ['Hello', 'World']; Object.keys(a) // ["0", "1"] Object.getOwnPropertyNames(a) // ["0", "1", "length"]
其余静态方法:(传送门)
1)对象属性模型的相关方法
Object.getOwnPropertyDescriptor()
:获取某个属性的描述对象。Object.defineProperty()
:经过描述对象,定义某个属性。定义key为Symbol的属性的方法之一。Object.defineProperties()
:经过描述对象,定义多个属性。2)控制对象状态的方法
Object.preventExtensions()
:防止对象扩展。Object.isExtensible()
:判断对象是否可扩展。Object.seal()
:禁止对象配置。Object.isSealed()
:判断一个对象是否可配置。Object.freeze()
:冻结一个对象。Object.isFrozen()
:判断一个对象是否被冻结。3)原型链相关方法
Object.assign(target, ...sources)
:用于将全部可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。Object.create()
:该方法能够指定原型对象和属性,返回一个新的对象。Object.getPrototypeOf()
:获取对象的Prototype
对象。三、Object实例方法
定义在Object.prototype
的·对象称为实例方法,全部Object的实例对象都继承了这些方法。Object
实例对象的方法,主要有如下六个。
Object.prototype.valueOf()
:返回当前对象对应的值。Object.prototype.toString()
:返回当前对象对应的字符串形式。检测对象类型。 Object.prototype.toLocaleString()
:返回当前对象对应的本地字符串形式。Object.prototype.hasOwnProperty()
:判断某个属性是否为当前对象自身的属性,仍是继承自原型对象的属性。Object.prototype.isPrototypeOf()
:判断当前对象是否为另外一个对象的原型。Object.prototype.propertyIsEnumerable()
:判断某个属性是否可枚举。之因此会说到这个判断问题,主要缘由是typeof
是不太靠谱的。首先JavaScript是动态数据类型的语言,不少类型检查是没必要要的。在具体实现上的问题,在实际的项目应用中,typeof
也只有两个用途,就是检测一个元素是否为undefined
,或者是否为function
。由下面的表格可见一斑:
Value function typeof ------------------------------------- "foo" String string new String("foo") String object 1.2 Number number new Number(1.2) Number object true Boolean boolean new Boolean(true) Boolean object new Date() Date object new Error() Error object [1,2,3] Array object new Array(1, 2, 3) Array object new Function("") Function function /abc/g RegExp object new RegExp("meow") RegExp object {} Object object new Object() Object object
若是仍是要判断的话,公认的靠谱解法是 Object.prototype.toString.call(x) === '[object type]'
。具体实现能够参考jQuery.type()
源码。另外经过构造函数建立的对象均可以用 instanceof
检查。