数据类型:能够表示并操作的值的类型。
JavaScript的数据类型分为两类:
(1) 原始类型(primitive type):
u 数字(Number)
· 所有数字均用64位浮点数值表示,然而实际的操作(比如数组索引、位运算符等)则是基于32位整数;
· 一旦超过最大值或最小值(溢出)则由Infinity或-Infinity来表示,此时所有的运算结果都是无穷大值(保留正负号);
· 下溢就是当运算结果无限接近于零正数下溢返回0,负数下溢返回负零(在作为除数的时候和正零不相等);
· 被0整除不会报错,产生的是Infinity或-Infinity,但是零除以零返回NaN;
· *负数是由求反运算符计算得出的,负号并不是数字直接量语法的组成部分。
· 支持进制:十进制、十六进制、八进制(某些情况下支持,在ES6的严格模式下不支持)
· NaN(Not a Number)也是一个数值;
· NaN不等于任何值,包括它自己,可以用全局函数isNaN()来检测;
u 字符串(String)
· ECMAScript5中可以拆分成数行,每行必须以反斜线(\)结束;
· *注意区分substring、slice、substr;
(slice和substring接收的是起始位置和结束位置(不包括结束位置),而substr接收的则是起始位置和所要返回的字符串长度;
当接收的参数是负数时,slice会将它字符串的长度与对应的负数相加,结果作为参数;substr则仅仅是将第一个参数与字符串长度相加后的结果作为第一个参数;substring则干脆将负参数都直接转换为0)
· 字符串的方法不会改变字符串本身,而是返回新字符串;
u 布尔值(Boolean)
(各自特殊类型的唯一成员)
u null(空)
· 特殊的对象值,含义是非对象;
u undefined(未定义)
· 预定义的全局变量;
· ==判断相等,===严格不相等;
(2) 对象类型(object type):
u 对象(“命名值”的无序集合)
*全局对象(global object)
· 包含一组定义的初始属性:全局属性(undefined、Infinity、NaN等)、全局函数、构造函数(Date、RegExp、String、Object、Array)、全局对象(Math、JSON等);
· 在代码最顶级可以使用this来引用全局对象;
· 客户端JavaScript中Window对象充当了全局对象,属性window引用其自身,可以代替this;
*包装对象
· 存取字符串、数字或布尔值的属性时创建的临时对象;
· 可以通过构造函数来显式创建包装对象(比如String()、Number()等)
· 原始值的比较是值的比较,对象的比较是引用的比较。
*显式类型转换
(1)使用带参数的构造函数创建包装对象
(2)用运算符做隐式的类型转换
(3)parse类转换函数
ECMAScript中有三种对象可以被创建并且被使用:
(1) 本地对象(native object):就是ECMA-262定义的类(引用类型),包括(Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError)
(2) 内置对象(built-in object):由ECMAScript实现提供的、独立于宿主环境的所有对象、在ECMAScript程序执行时开始出现(只有两个:Global和Math)。
*内置对象都是本地对象。
(3) 宿主对象(host object):所有非本地对象都是宿主对象,所有BOM和DOM对象都是宿主对象。
对象和原始值之间的转换:
(1) 对象转换为原始值:
a. 到布尔值:所有对象都转换成true(包括包装对象);
b. 到字符串(只适用于本地对象):如果对象具有toString方法则调用这个方法或返回原始值;如果没有toString方法或并不返回原始值则调用valueOf方法;否则抛出类型错误异常;
c. 到数字(只适用于本地对象):先valueOf后toString;
d. 日期类特殊:只使用对象到字符串的转换模式。
(2) 原始值转换成对象:
声明提前:变量在声明之前已经可用。
当声明一个js全局变量时,实际上是定义了全局对象的一个属性。
声明上下文对象:局部变量当做跟函数调用相关的某个对象的属性。
JavaScript核心特征:“原型式”继承;
对象最常见的用法是创建、设置、查找、删除、检测和枚举它的属性。
属性特性:
(1) 可写(writable attribute),表明是否可以设置该属性的值;
(2) 可枚举(enumerable attribute),表明是否可以通过for/in循环返回该属性;
(3) 可配置(configurable attribute),表明时候可以删除或修改该属性。
对象特性:
(1) 对象的原型(prototype)指向另外一个对象,本对象的属性继承自它的原型对象;
(2) 对象的类(class)是一个标识对象类型的字符串;
(3) 对象的扩展标记(extensible flag)指明了是否可以向该对象添加新属性。
三类js对象和两类属性:
(1) 内置对象
(2) 宿主对象
(3) 自定义对象(user-defined object)是由运行中的JavaScript代码创建的对象;
(4) 自有属性(own property)是直接在对象中定义的属性;
(5) 继承属性(inherited property)是在对象的原型对象中定义的属性。
*对象直接量中的最后一个属性后的逗号将忽略,且在ECMAScript 3的大部分实现中也可以直接忽略这个逗号,但是在IE中报错。
属性访问:
(1) o中的属性p是只读的:不能给制度属性重新赋值(defineProperty()方法中有一个例外,可以对可配置的只读属性重新赋值);
(2) o中的属性p是继承属性,且它是只读的:不能通过同名自有属性覆盖只读的继承属性;
(3) o中不存在自有属性p:o没有使用setter方法继承属性p,并且o的可扩展性是false。如果o中不存在p,而且没有setter方法可供调用,则p一定会添加至o中。但如果o不是可扩展的,那么在o中不嗯呢该定义新属性;
删除属性:
· delete只是断开实行和宿主对象的联系,而不会去操作属性中的属性;
· 只能删除自有属性,不能删除继承属性(要删除继承属性必须从定义这个属性的原型对象上删除它,而且这会影响到所有继承自这个原型的对象)。
· 由于已经删除的属性的引用依然存在,因此在js的某些实现中,可能因为这种不严谨的diamante而造成内存泄漏。所以在销毁对象的时候,要遍历属性中的属性,依次删除。
· delete不能删除那些可配置性为false的属性(尽管可以删除不可扩展对象的可配置属性)。
检测属性:
(1) in运算符:如果对象的自有属性或继承属性中包含这个属性则返回true;
(2) hasOwnProperty:用来检测给定的名字时候是对象的自有属性,继承属性返回false;
(3) propertyIsEnumerable:只有检测到自有属性且这个属性的可枚举性是true时才返回true;
(4) 属性查询:!==(注意,当属性被显式赋值为undefined的时候一定要用in遍历)
枚举属性:
(1) for/in循环
(2) Object.keys方法:返回一个数组,这个数组由对象中可枚举的自有属性的名称组成;
(3) Object.getOwnPropertyNames方法:返回对象中所有自有属性的名称(包含不可枚举的属性);
存取器属性(accessorproperty)的四个特性:
读取(get)、写入(set)、可枚举性和可配置性;
数据属性(data property)的四个特性:
值(value)、可写性(writable)、可枚举性(enumerable)、可配置性(configurable);
Object.defineProperty要么修改已有属性要么新建自有属性,但不能修改继承属性;
Object.defeineProperties方法修改或创建多个属性;
对象的三个属性:
u 数组(带编号的值的有序集合)
u 函数
构造函数(constructor):用来初始化一个新建的对象(使用new预运算符);
每个构造函数定义了一类对象(class):由构造函数初始化的对象组成的集合
类可以看做是对象类型的子类型。
Date(日期类):定义了代表日期的对象;
RegExp(正则类):定义了表示正则表达式的对象;
Error(错误类):定义了那些表示JavaScript程序中运行时错误和语法错误的对象。
只有null和undefined是无法拥有方法的值。
另一种分法:
(1) 可变类型(mutable)
对象、数组
(2) 不可变类型(immutable)
数字、布尔值、null、undefined、字符串
严格模式和非严格模式:
1. 在严格模式中禁止使用with语句;
2. 在严格模式中,所有的变量都要先声明,如给一个未声明的变量、函数、函数参数、catch从句参数或全局对象的属性赋值,将会抛出一个引用错误异常(在非严格模式中,这种隐式声明的全局变量的方法是给全局对象新添加一个新属性),也就是说在这里声明提前是不存在的,必须先声明再使用;
3. 在严格模式中,调用的函数(不是方法)中的一个this值是undefined。(在非严格模式中,调用的函数中的this值总是全局对象)可以利用这种特性来判断js实现是否支持严格模式;
4. 在严格模式中,当通过call()或apply()来调用函数时,其中的this值就是通过call()或apply()传入的第一个参数(在非严格模式中,null和undefined值被全局对象和转换为对象的非对象值所替代)。
5. 在严格模式中,给只读属性复制和给不可扩展的对象创建新成员都将抛出一个类型错误异常(在非严格模式中,这些操作只是简单地操作失败,不会报错);
6. 在严格模式中,传入eval()的代码不能在调用程序所在的上下文中声明变量或定义函数,而在非严格模式中是可以这样做的。相反,变量和函数的定义是在eval()创建的新作用域中,这个作用域在eval(0返回时就弃用了;
7. 在严格模式中,函数里的arguments对象拥有传入函数值的静态副本。在非严格模式中,arguments对象具有“魔术般”的行为,arguments里的数组元素和函数参数都是指向同一个值的引用;
8. 在严格模式中,当delete运算符后跟随非法的标识符(比如变量、函数、函数参数)时,将会抛出一个语法错误异常(在非严格模式中,这种delete表达式什么也没做,并返回false)。
9. 在严格模式中,试图删除一个不可配置的属性将抛出一个类型错误异常(在非严格模式中,delete表达式操作失败)。
10.在严格模式中,在一个对象直接量中定义两个或者多个同名的参数将产生一个语法错误(在非严格模式中不会报错);
11.在严格模式中是不允许使用八进制整数直接量的(非严格模式允许);
12.在严格模式中,标识符eval和arguments当做关键字,它们的值是不能更改的,不能给这些标识符赋值,也不能把它们声明为变量、用作函数名、用作函数参数或用作catch块的标识符;
在严格模式中限制了对调用栈的检测能力,在严格模式的函数中,
arguments
。
caller
和
arguments
、
callee
都会抛出一个类型错误异常、严格模式的函数同样具有
caller
和
arguments
属性,当访问这两个属性时将抛出类型错误异常。