ES5-数据类型补充

本篇主要是对ES5中常见的数据类型进行一些补充和说明html

基本数据类型

常常被问及一些基本的数据类型,我也不打算深刻研究,某个数据究竟在内存中是怎么样存储的。 JavaScript是一门弱类型的语言,JavaScript变量的类型取决于变量值的类型。正则表达式

你须要知道的一些基本数据类型express

  • number 数字
  • string 字符串
  • boolean 布尔
  • undefined Undefined未定义
  • null null空值

使用运算符 typeof 对以上进行运算你会发现除了null为object以外,其余都是对应的字符串形式 number,string,boolean都有其对应的包装函数 Number,String,Boolean编程

在我本身的定义中,对象是键值对的组合,是一个词典,因为Function也能存储对应的属性,故我将其归结到Object类型,因此,除了以上五种以外,也就还剩Object类型数组

使用方式

// 直接量形式使用便可
var _num = 1;
var _str = "string";
var _bool = true;
var _null = null;
var _undefined = undefined;
复制代码

对number的说明:因为数字是能够带小数的,故还可能有如下形式bash

var num = .1;   // or: var num = 1.;
复制代码

引用数据类型

对C有了解的可能就会知道,有些变量存储单元是对应的直接值,而有些存储单元存储的某个内存地址,地址所指向的位置就是其真实的数据存储的位置(以上不考虑堆栈中的其余数据和状态所表示的结构)。数据结构

基本类型和引用类型的异同

我没有特别详尽的语言去概述基本类型和引用类型的异同ide

  • 基本类型是按值访问的,且不能更改基本类型的值,好比你不可能把5改为6吧
  • 基本类型是在序列中直接能够进行大小比较的,好比 5 > 4
  • 基本类型是存储在栈内存中的
  • 引用类型是存储在栈内存和堆内存中的,是按引用访问的
  • 引用类型的值是可变的
    var obj = {};
    obj.name = "newName"
    复制代码
  • 引用类型相互比较的时候,只能比较地址是否同样

若是咱们本身不搞事情,typeof能够区分function和其余引用类型,经过instanceof运算符也能推断出某个对象是不是某个构造函数的实例,经过Object.prototype.toString能精确获取。可是在ES6中,若是本身要放炸弹:Symbol.hasInstance -> instanceof,Symbol.toStringTag -> Object.prototype.toString,也请尽可能考虑一下爆炸的范围函数

// 盗用jQuery中的各类类型校验函数
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
	class2type[ "[object " + name + "]" ] = name.toLowerCase();
});
复制代码

常见引用类型

Object 普通对象

咱们常常看到的多数是Object的实例,即直接由函数Object构造调用而来的实例post

var obj = {};   //直接量形式
obj = new Object();
obj = Object(); // 这种形式对不一样的参数会有不一样的处理,参见如下说明
// 如下方式我也写一下
obj = eval('({})');
obj = new Function('return {}')();
复制代码

Date 日期操做

常使用的日期的操做,这个我以为查文档可能会更好,我比较喜欢moment.js这个库。

RegExp

正则表达式:var expression = /pattern/flags; 具体也本身查文档更好,推荐查看犀牛书。我也把本身的记录分享出来

ES3中规定,一个正则表达式直接量会在执行到它时转换为RegExp对象,同一段代码所表示的正则表达式直接量的每次运算都返回同一个对象
ES5与ES3相反,每次都返回新的对象

直接量字符
    ^ $ . ? * + = ! : | \ / () [] {}	\t \n...
字符类
    [...] [^...] . \w \W \s \S \d \D [\b]
重复
    {n, m} {n,} {n} * + ?(可选)
    非贪婪重复:尽量的多的匹配字符,若不须要,则只须要在上述重复后面添加 '?'
    注意:正则表达式的模式匹配老是会寻找字符串中第一个可能匹配的位置
        例: /a+?b/ -> 'aaab'	该匹配从第一个字符开始,因此全匹配
选择、分组、引用
    | 用于分隔供选择的字符,选择项的尝试匹配是从左到右,直到发现匹配项,一旦左边匹配,就会忽略右边
    () 
        用于将单独的项组合成子表达式;
        在完整的模式中定义子模式,能够进行抽取
        表达式(?:...)只是分组,而不会生成引用,即分组不会编码
指定匹配位置
    \b匹配单词边界,位于\w \W之间的边界or单词与字符串的开始或结尾之间的边界(匹配发生的合法的位置) ^ $
    \B将把匹配的锚点定位在不是单词边界的地方 /\B[Ss]cript/ == JavaScript|postscript !=script|Scripting
    任意表达式均可以做为锚点条件
        (?=) 先行断言
        (?!) 负先行断言
    锚字符
        ^		匹配字符串开头,多行检索中,匹配一行的开头
        $		..........结尾
        \b 		匹配一个单词边界,注意 [\b]匹配的是退格符
        \B 		匹配非单词边界位置
        (?=p)	零宽正向先行断言,要求接下来的字符都与p匹配,但不能包括匹配p的那些字符
        (?!p)	零宽负向........,要求............不与p匹配,...
复制代码

Array 数组类型

数组类型:存放一组值的数据结构,对其基本的操做和函数须要牢记于心

构造函数的说明:参数若是只有一个,且是数字则表示长度,其余则做为元素,ES6中Array.of和Array.from对其进行了补充的操做

会改变数组的操做:pop/push、shift/unshift、splice
遍历:forEach、some、every、filter、map、reduce/reduceRight
其余操做:slice、concat、sort、indexOf、lastIndexOf

filter、map、reduce是函数式中针对集合编程的基础:数据流+高阶函数

Function 函数类型

ES5中所见的函数都由Function构造调用而来,依据官方说明,函数的产生式有以下形式

  1. 函数声明:function Identifier(FormalParameterList){FunctionBody}
  2. 匿名函数表达式:function(FormalParameterList){FunctionBody}
  3. 命名函数表达式:function Identifier(FormalParameterList){FunctionBody}

基本包装类型

为了便于操做基本类型的值,ECMAScript提供了三种特殊的引用类型:Number、String、Boolean

var _num = new Number(1);   // 千万不要省略new运算符,不然是作类型转换
var _str = new String("string");
var _bool = new Boolean(true);

// 对Object函数调用时的说明
console.info(Object(1));
console.info(Object("string"));
console.info(Object(true));
// 对以上三种基本数据,会返回对应的包装类型

// 当参数是null、undefined时直接生成一个新的对象
console.info(Object(null));
console.info(Object(undefined));

// 当参数是引用类型时直接返回该引用
console.info(Object({key: 'value'}));
复制代码

探究自动包装的特征
后台隐式建立对应包装对象,在这个实例上调用指定方法,最后销毁这个实例

String.prototype.getSelf = function(){
    return this;
};
var result = "string".getSelf();
console.info(result, typeof result);    //String{"string"} "object"
// delete String.prototype.getSelf;

var num = 1;
console.info(num instanceof Number);    // false
// console.info("toString" in num); // in 不能用在基本类型上

Number.prototype.getFn = function(){}

// 12.6.4 for-in 语句
// 产生式 IterationStatement : for ( LeftHandSideExpression in Expression ) Statement 按照下面的过程执行 :
// 1. 令 exprRef 为解释执行 Expression 的结果 .
// 2. 令 experValue 为 GetValue(exprRef).
// 3. 若是 experValue 是 null 或 undefined,返回 (normal, empty, empty).
// 4. 令 obj 为 ToObject(experValue).
for(var attr in 1){
    console.info(attr); // getFn
}

 // 对此的说明存在于 规范12.10中对产生式with中进行数据类型转换
with(1){
    console.info(getFn);    // 输出函数
}
复制代码

总结:当基本类型数据在作存取运算时,会发生自动转换为包装对象的操做

内置对象类型:global/window、Math

提供的对应的可操做方法 请自行查阅文档

valueOf、toString、toPrimitive的说明

ToPrimitive抽象操做:将参数转为非对象类型,检查该值是否有 valueOf() 方法。若是有而且返回基本类型值,就使用该值进行强制类型转换。若是没有就使用 toString()的返回值(若是存在)来进行强制类型转换。

var _valueOf = Number.prototype.valueOf;
Number.prototype.valueOf = function(){
    console.info("valueOf", typeof this);    //"object"
    var result = _valueOf.call(this);
    console.info("valueOf-result", result, typeof result);  // 原始值
    // return this;
    return result;
};
var _toString = Number.prototype.toString;
Number.prototype.toString = function(){
    console.info("toString", typeof this);
    var result = _toString.call(this);

    console.info("toString-result", result, typeof result); // 原始值的字符串形式
    return _toString.call(this);
};
var _num = new Number(true);
console.warn(100 + _num);
复制代码

object -> string
1. 调用toString方法,若是返回一个原始值,将这个值转为String并返回
2. 没有toString or 返回的不是原始值,调用valueOf
3. JavaScript没法从toString或者valueOf方法获取一个原始值,抛出一个类型异常

object -> number
1. 调用valueOf,若是返回一个原始值,转为number并返回
2. 调用toString,若是返回一个原始值,转为number并返回
3. 不然抛出异常

类型 valueOf返回值 备注 toStrig返回值
Boolean 对应的基本类型 对应基本类型值的字符串形式
Number 对应的基本类型 对应基本类型值的字符串形式
String 对应的基本类型 对应基本类型值的字符串形式
Array 数组 引用类型 Array.toString一致
Function 函数 引用类型 function的字符串表示形式
Object 对象 引用类型 '[object Object]'
RegExp 正则对象 引用类型 字面量字符串形式
Error error对象 引用类型

数据类型变换

通常转换形式:

ToString:非字符串到字符串的转换

普通对象,除非自定义toString函数,不然调用内置的toString进行转换;其余对象强制类型转换,请参考上述

ToNumber:

true: 1, false: 0, "":0, null: 0, undefined: NaN
对象类型转换,则调用抽象操做ToPrimitive

ToBoolean:

全部假值 :undefined null false 0 -0 NaN "" 为false,非假值都是true

显示强制类型转换

  1. 字符串和数字的相互转换:Number、String(没有new关键字)
  2. 显示函数解析数字字符串:parseInt/parseFloat
  3. 显示转换为布尔值:Boolean构造函数,运算符!、&&、||都是直接转换

隐式类型转换

  1. 字符串和数字之间的隐式类型转换

    若是某个操做数是字符串或者可以经过如下步骤转换为字符串的话, + 将进行拼接操做。
    若是其中一个操做数是对象(包括数组)

    首先对其调用ToPrimitive 抽象操做(规范 9.1 节),
    该抽象操做再调用 [[DefaultValue]] (规范 8.12.8节),以数字做为上下文

    运算符+和String转换区别

    ToPrimitive抽象操做 在运算符+时,先调用valueOf,而后调用toString 而String显示转换时,直接调用toString

  2. 布尔值到数字隐式类型转换 true -> 1 false -> 0

  3. 隐式强制类型转换为布尔值
    if/for/while/do..while的条件判断
    ?..:.. && ||

  4. || 和 &&
    选择器运算符,返回值并不必定是布尔类型,而是两个操做数其中一个的值

宽松相等和严格相等

== 容许在相等比较中进行强制类型转换,而 === 不容许

11.9.3.1 的最后定义了对象(包括函数和数组)的宽松相等 == 。两个对象指向同一个值时即视为相等,不发生强制类型转换
11.9.3 节中还规定, == 在比较两个不一样类型的值时会发生隐式强制类型转换,会将其中之一或二者都转换为相同的类型后再进行比较

1.1 字符串和数字
(1) 若是 Type(x) 是数字, Type(y) 是字符串,则返回 x == ToNumber(y)的结果。
(2) 若是 Type(x) 是字符串, Type(y) 是数字,则返回 ToNumber(x) == y的结果。

1.2 其余类型和布尔值
(1) 若是 Type(x) 是布尔类型,则返回 ToNumber(x) == y 的结果;
(2) 若是 Type(y) 是布尔类型,则返回 x == ToNumber(y) 的结果。

1.3 null和undefined比较
(1) 若是 x 为 null , y 为 undefined ,则结果为 true 。
(2) 若是 x 为 undefined , y 为 null ,则结果为 true 。

1.4 对象和非对象比较
(1) 若是 Type(x) 是字符串或数字, Type(y) 是对象,则返回 x == ToPrimitive(y)的结果;
(2) 若是 Type(x) 是对象, Type(y) 是字符串或数字,则返回 ToPromitive(x) == y的结果。
封装对象会自动进行拆封

简记:boolean->number, string->number, null等于undefined, 对象类型转为基本类型

console.info([] == 0);  // true
console.info(false == []);  // true
console.info(null == 0);    // false
console.info([] + 1);   // "1"
console.info({} + 1);   // 1 :由于js在执行过程当中语句优先,{}被解析为代码块
console.info([] + {}, {} + []); // 多少本身慢慢能够分得清楚了
复制代码

抽象关系比较

比较双方首先调用 ToPrimitive ,若是结果出现非字符串,就根据 ToNumber 规则将双方强制类型转换为数字来进行比较。 若是比较双方都是字符串,则按字母顺序来进行比较

参考资料:
《You Don't Know JS: Types & Grammar》中卷
《JAVASCRIPT 语言精髓与编程实践》
《JavaScript 高级程序设计》
《JavaScript 权威指南》
《ES5文档》(www.ecma-international.org/ecma-262/5.…)

相关文章
相关标签/搜索