乐趣区

关于node.js:JavaScript-基础数据类型

根底数据类型

转载请注明出处,github 地址 JavaScript 根底数据类型

js 中的数据类型

JavaScript 中共有七种内置数据类型,包含 根本类型 对象类型

根本类型

根本类型分为以下六种:

  • string(字符串)
  • boolean(布尔值)
  • number(数字)
  • symbol(符号)
  • null(空值)
  • undefined(未定义)

留神

  1. stringnumberbooleannull undefined 这五种类型统称为 原始类型(Primitive),示意不能再细分上来的根本类型;
  2. symbol是 ES6 中新增的数据类型,symbol 示意举世无双的值,通过 Symbol 函数调用生成,因为生成的 symbol 值为原始类型,所以 Symbol 函数不能应用 new 调用;
  3. nullundefined 通常被认为是非凡值,这两种类型的值惟一,就是其自身。

对象类型

对象类型也叫援用类型,arrayfunction 是对象的子类型。对象在逻辑上是属性的无序汇合,是寄存各种值的容器。对象值存储的是援用地址,所以和根本类型值不可变的个性不同,对象值是可变的。

弱类型语言

JavaScript 是弱类型语言,而且 JavaScript 申明变量的时候并没有预先确定的类型,变量的类型就是其值的类型,也就是说 变量以后的类型由其值所决定 , 夸大点说上一秒种的String,下一秒可能就是个Number 类型了,这个过程可能就进行了某些操作产生了强制类型转换。尽管弱类型的这种 不须要预先确定类型 的个性给咱们带来了便当,同时也会给咱们带来困扰,为了能充分利用该个性就必须把握类型转换的原理。

js 中的强制转换规则

ToPrimitive(转换为原始值)

ToPrimitive对原始类型不产生转换解决,只 针对援用类型(object)的,其目标是将援用类型(object)转换为非对象类型,也就是原始类型。

ToPrimitive 运算符 承受一个值,和一个可选的冀望类型作参数 ToPrimitive 运算符将值转换为非对象类型,如果对象有能力被转换为不止一种原始类型,能够应用可选的 冀望类型 来暗示那个类型。

转换后的后果 原始类型 是由冀望类型决定的,冀望类型其实就是咱们传递的 type。间接看上面比较清楚。
ToPrimitive 办法大略长这么个样子具体如下。

/**
* @obj 须要转换的对象
* @type 冀望转换为的原始数据类型,可选
*/
ToPrimitive(obj,type)
type 不同值的阐明
  • type 为string:
  1. 先调用 objtoString办法,如果为原始值,则return,否则进行第 2 步
  2. 调用 objvalueOf办法,如果为原始值,则return,否则进行第 3 步
  3. 抛出TypeError 异样
  • type 为number:
  1. 先调用 objvalueOf办法,如果为原始值,则return,否则进行第 2 步
  2. 调用 objtoString办法,如果为原始值,则return,否则第 3 步
  3. 抛出TypeError 异样
  • type 参数为空
  1. 该对象为Date,则 type 被设置为String
  2. 否则,type 被设置为Number
Date 数据类型非凡阐明:

对于 Date 数据类型,咱们更多冀望取得的是其转为工夫后的字符串,而非毫秒值(工夫戳),如果为 number,则会取到对应的毫秒值,显然字符串应用更多。
其余类型对象依照取值的类型操作即可。

ToPrimitive总结

ToPrimitive转成何种原始类型,取决于 type,type 参数可选,若指定,则依照指定类型转换,若不指定,默认依据实用状况分两种状况,Datestring,其余对象为number。那么什么时候会指定 type 类型呢,那就要看上面两种转换形式了。

toString

Object.prototype.toString()

toString() 办法返回一个示意该对象的字符串。

每个对象都有一个 toString() 办法,当对象被示意为文本值时或者当以冀望字符串的形式援用对象时,该办法被主动调用。

这里先记住,valueOf()toString() 在特定的场合下会自行调用。

valueOf

Object.prototype.valueOf()办法返回指定对象的原始值。

JavaScript 调用 valueOf() 办法用来把对象转换成原始类型的值(数值、字符串和布尔值)。然而咱们很少须要本人调用此函数,valueOf 办法个别都会被 JavaScript 主动调用。

不同内置对象的 valueOf 实现:

  • String => 返回字符串值
  • Number => 返回数字值
  • Date => 返回一个数字,即工夫值, 字符串中内容是依赖于具体实现的
  • Boolean => 返回 Boolean 的 this 值
  • Object => 返回 this

对照代码会更清晰一些:

var str = new String('123');
console.log(str.valueOf());//123

var num = new Number(123);
console.log(num.valueOf());//123

var date = new Date();
console.log(date.valueOf()); //1526990889729

var bool = new Boolean('123');
console.log(bool.valueOf());//true

var obj = new Object({valueOf:()=>{return 1}})
console.log(obj.valueOf());//1
Number

Number运算符转换规则:

  • null 转换为 0
  • undefined 转换为 NaN
  • true 转换为 1,false 转换为 0
  • 字符串转换时遵循数字常量规定,转换失败返回NaN

留神:对象这里要先转换为原始值,调用 ToPrimitive 转换,type 指定为 number 了,持续回到 ToPrimitive 进行转换。

String

String 运算符转换规则

  • null 转换为 'null'
  • undefined 转换为 undefined
  • true 转换为 'true'false 转换为 'false'
  • 数字转换遵循通用规定,极大极小的数字应用指数模式

留神:对象这里要先转换为原始值,调用 ToPrimitive 转换,type就指定为 string 了,持续回到 ToPrimitive 进行转换 (下面有将到ToPrimitive 的转换规则)。

String(null)                 // 'null'
String(undefined)            // 'undefined'
String(true)                 // 'true'
String(1)                    // '1'
String(-1)                   // '-1'
String(0)                    // '0'
String(-0)                   // '0'
String(Math.pow(1000,10))    // '1e+30'
String(Infinity)             // 'Infinity'
String(-Infinity)            // '-Infinity'
String({})                   // '[object Object]'
String([1,[2,3]])            // '1,2,3'
String(['koala',1])          //koala,1
Boolean

ToBoolean 运算符转换规则

除了下述 6 个值转换后果为 false,其余全副为 true

  1. undefined
  2. null
  3. -0
  4. 0 或 +0
  5. NaN
  6. ”(空字符串)

假值以外的值都是真值。其中包含所有对象(包含空对象)的转换后果都是 true,甚至连false 对应的布尔对象 new Boolean(false) 也是true

Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false

Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true

转换规则不同场景利用

什么时候主动转换为 string 类型

  • 在没有对象的前提下

    字符串的主动转换,次要产生在字符串的 加法运算 时。当一个值为字符串,另一个值为非字符串,则后者转为字符串。

'2' + 1 // '21'
'2' + true // "2true"
'2' + false // "2false"
'2' + undefined // "2undefined"
'2' + null // "2null"
  • 当有对象且与对象 + 时候
//toString 的对象
var obj2 = {toString:function(){return 'a'}
}
console.log('2'+obj2)
// 输入后果 2a

// 惯例对象
var obj1 = {
   a:1,
   b:2
}
console.log('2'+obj1);// 输入后果 2[object Object]

// 几种非凡对象
'2' + {} // "2[object Object]"
'2' + [] // "2"
'2' + function (){} // "2function (){}"
'2' + ['koala',1] // 2koala,1

对上面 '2'+obj2 具体举例说明如下:

  1. 右边为 stringToPrimitive 原始值转换后不发生变化
  2. 左边转化时同样依照 ToPrimitive 进行原始值转换,因为指定的 type 是 number,进行ToPrimitive 转化调用obj2.valueof(), 失去的不是原始值,进行第三步
  3. 调用toString() return 'a'
  4. 符号两边存在 string,而且是+ 号运算符则都采纳 String 规定转换为 string 类型进行拼接
  5. 输入后果2a

对上面 '2'+obj1 具体举例说明如下:

  1. 右边为 stringToPrimitive 转换为原始值后不发生变化
  2. 左边转化时同样依照 ToPrimitive 进行原始值转换,因为指定的 type 是 number,进行ToPrimitive 转化调用obj2.valueof(), 失去{a: 1, b: 2}
  3. 调用toString() return [object Object]
  4. 符号两边存在 string,而且是 + 号运算符则都采纳String 规定转换为 string 类型进行拼接
  5. 输入后果2[object Object]

代码中几种非凡对象的转换规则基本相同,就不一一阐明,大家能够想一下流程。

留神:不论是对象还不是对象,都有一个转换为原始值的过程,也就 是 ToPrimitive转换,只不过原始类型转换后不发生变化,对象类型才会产生具体转换。

string 类型转换开发过程中可能出错的点:
var obj = {width: '100'};

obj.width + 20 // "10020"

预期输入后果 120 理论输入后果 10020

什么时候主动转换为 Number 类型

  • 有加法运算符,然而无 String 类型的时候,都会优先转换为 Number 类型

    例子:

    true + 0 // 1
    true + true // 2
    true + false //1
  • 除了加法运算符,其余运算符都会把运算主动转成数值。

例子:

'5' - '2' // 3
'5' * '2' // 10
true - 1  // 0
false - 1 // -1
'1' - 1   // 0
'5' * []    // 0
false / '5' // 0
'abc' - 1   // NaN
null + 1 // 1
undefined + 1 // NaN

// 一元运算符(留神点)+'abc' // NaN
-'abc' // NaN
+true // 1
-false // 0

留神:null转为数值时为 0,而 undefined 转为数值时为NaN

判断等号也放在 Number 外面非凡阐明

== 形象相等比拟与 + 运算符不同,不再是 String 优先,而是 Number 优先。
上面列举 x == y 的例子

  1. 如果 x,y 均为 number,间接比拟
    没什么可解释的了
1 == 2 //false
  1. 如果存在对象,ToPrimitive()type 为 number 进行转换,再进行前面比拟
var obj1 = {valueOf:function(){return '1'}
}
1 == obj1  //true
//obj1 转为原始值,调用 obj1.valueOf()
// 返回原始值 '1'
//'1'toNumber 失去 1 而后比拟 1 == 1
[] == ![] //true
//[]作为对象 ToPrimitive 失去 ''  
//![]作为 boolean 转换失去 0 
//'' == 0 
// 转换为 0==0 //true
  1. 存在 boolean,依照ToNumberboolean转换为 1 或者 0,再进行前面比拟
//boolean 先转成 number,依照下面的规定失去 1  
//3 == 1 false
//0 == 0 true
3 == true // false
'0' == false //true

4. 如果 xstringynumberx 转成 number 进行比拟

//'0' toNumber()失去 0  
//0 == 0 true
'0' == 0 //true

什么时候进行布尔转换

  • 布尔比拟时
  • if(obj) , while(obj) 等判断时或者 三元运算符只可能蕴含布尔值

条件局部的每个值都相当于false,应用否定运算符后,就变成了true

if ( !undefined
  && !null
  && !0
  && !NaN
  && !''
) {console.log('true');
} // true

// 上面两种状况也会转成布尔类型
expression ? true : false
!! expression

数据类型判断

面试官问:如何判断数据类型?怎么判断一个值到底是数组类型还是对象?

三种形式,别离为 typeofinstanceof Object.prototype.toString()

typeof

通过 typeof操作符来判断一个值属于哪种根本类型。

typeof 'seymoe'    // 'string'
typeof true        // 'boolean'
typeof 10          // 'number'
typeof Symbol()    // 'symbol'
typeof null        // 'object' 无奈断定是否为 null
typeof undefined   // 'undefined'

typeof {}           // 'object'
typeof []           // 'object'
typeof(() => {})    // 'function'

下面代码的输入后果能够看出,

  1. null 的断定有误差,失去的后果

如果应用 typeofnull失去的后果是object

  1. 操作符对对象类型及其子类型,例如函数(可调用对象)、数组(有序索引对象)等进行断定,则除了函数都会失去 object 的后果。

综上能够看出 typeOf 对于判断类型还有一些有余,在对象的子类型和 null 状况下。

instanceof

通过 instanceof 操作符也能够对对象类型进行断定,其原理就是测试构造函数的 prototype 是否呈现在被检测对象的原型链上。

[] instanceof Array            // true
({}) instanceof Object         // true
(()=>{}) instanceof Function   // true

复制代码留神:instanceof 也不是万能的。
举个例子:

let arr = []
let obj = {}
arr instanceof Array    // true
arr instanceof Object   // true
obj instanceof Object   // true

在这个例子中,arr 数组相当于 new Array() 出的一个实例,所以 arr.__proto__ === Array.prototype,又因为 Array 属于 Object 子类型,即 Array.prototype.__proto__ === Object.prototype,因而 Object 构造函数在 arr 的原型链上。所以 instanceof 依然无奈优雅的判断一个值到底属于数组还是一般对象。

还有一点须要阐明下,有些开发者会说 Object.prototype.__proto__ === null,岂不是说 arr instanceof null 也应该为 true,这个语句其实会报错提醒右侧参数应该为对象,这也印证 typeof null 的后果为 object 真的只是 javascript 中的一个 bug

Object.prototype.toString()

Object.prototype.toString() 能够说是断定 JavaScript 中数据类型的终极解决办法了,具体用法请看以下代码:

Object.prototype.toString.call({})              // '[object Object]'
Object.prototype.toString.call([])              // '[object Array]'
Object.prototype.toString.call(() => {})        // '[object Function]'
Object.prototype.toString.call('seymoe')        // '[object String]'
Object.prototype.toString.call(1)               // '[object Number]'
Object.prototype.toString.call(true)            // '[object Boolean]'
Object.prototype.toString.call(Symbol())        // '[object Symbol]'
Object.prototype.toString.call(null)            // '[object Null]'
Object.prototype.toString.call(undefined)       // '[object Undefined]'

Object.prototype.toString.call(new Date())      // '[object Date]'
Object.prototype.toString.call(Math)            // '[object Math]'
Object.prototype.toString.call(new Set())       // '[object Set]'
Object.prototype.toString.call(new WeakSet())   // '[object WeakSet]'
Object.prototype.toString.call(new Map())       // '[object Map]'
Object.prototype.toString.call(new WeakMap())   // '[object WeakMap]'

咱们能够发现该办法在传入任何类型的值都能返回对应精确的对象类型。用法虽简单明了,但其中有几个点须要了解分明:

  • 该办法实质就是依靠 Object.prototype.toString() 办法失去对象外部属性 [[Class]]
  • 传入原始类型却可能断定出后果是因为对值进行了包装
  • nullundefined 可能输入后果是外部实现有做解决

NaN 相干

NaN的概念

NaN 是一个全局对象的属性,NaN 是一个全局对象的属性,NaN是一种非凡的 Number 类型。

什么时候返回 NaN(开篇第二道题也失去解决)

  • 无穷大除以无穷大
  • 给任意正数做开方运算
  • 算数运算符与不是数字或无奈转换为数字的操作数一起应用
  • 字符串解析成数字

一些例子:

Infinity / Infinity;   // 无穷大除以无穷大
Math.sqrt(-1);         // 给任意正数做开方运算
'a' - 1;               // 算数运算符与不是数字或无奈转换为数字的操作数一起应用
'a' * 1;
'a' / 1;
parseInt('a');         // 字符串解析成数字
parseFloat('a');

Number('a');   //NaN
'abc' - 1   // NaN
undefined + 1 // NaN
// 一元运算符(留神点)+'abc' // NaN
-'abc' // NaN

误区

toStringString 的区别

  • toString
  1. toString()能够将数据都转为字符串,然而 nullundefined不能够转换。

    console.log(null.toString())
    // 报错 TypeError: Cannot read property 'toString' of null
    
    console.log(undefined.toString())
    // 报错 TypeError: Cannot read property 'toString' of undefined
  2. toString()括号中能够写数字,代表进制

    二进制:.toString(2);

    八进制:.toString(8);

    十进制:.toString(10);

    十六进制:.toString(16);

  • String
  1. String()能够将 nullundefined转换为字符串,然而没法转进制字符串

    console.log(String(null));
    // null
    console.log(String(undefined));
    // undefined
退出移动版