必读:

JavaScript类型系统之基本数据类型与包装类型

Javascript对象Oject的强制类型转换

JavaScript筑基篇(二)->JavaScript数据类型

聊一聊valueOf和toString

深入理解JavaScript系列(12):变量对象(Variable Object)

JS的数据类型

  • 基本数据类型(其实也统称为基本型或原始型):undefined,null,number,boolean,string——按值访问

  • 一种复杂数据类型(引用型):Object——按址访问

数据类型介绍

undefined 类型:声明未定义

null 类型:null值表示一个空指针,初始化空对象可赋值为null

boolean 类型:注意true不一定等于1,而false也不一定等于0

要将一个值转为boolean型等价的值,有两种方案:

  • 一种是显式转换-调用类型转换函数Boolean()

  • 一种是自动转换-如if(value)中的value就会自动转化成为boolean值

各类型与boolean型之间值得转换关系:

数据类型 转换为true的值 转换为false的值
boolean true false
string 任何非空字符串 "" (空字符串)
bumber 任何非零数字值(包括无穷大) 0和NaN
undefined undefined
null null
Object 任何对象

number相关

将非number类型的值转换为number类型

  • 一种是隐式转换,如进行(\*、/)操作时,会自动其余类型的值转为number类型

  • 一种是显示转换-调用Number()、parseInt()、parseFloat()方法转换

Number():

  • 如果是boolean值,true和false将分别被替换为1和0

  • 如果是数字值,只是简单的传入和返回

  • 如果是null值,返回0

  • 如果是undefined,返回NaN

  • 如果是字符串,遵循下列规则:

    • 如果字符串中只包含数字,则将其转换为十进制数值,即”1“会变成1,”123“会变成123,而”011“会变成11(前导的0被忽略)

    • 如果字符串中包含有效的浮点格式,如”1.1“,则将其转换为对应的浮点数(同样,也会忽略前导0)

    • 如果字符串中包含有效的十六进制格式,例如”0xf“,则将其转换为相同大小的十进制整数值

    • 如果字符串是空的,则将其转换为0

    • 如果字符串中包含除了上述格式之外的字符,则将其转换为NaN

  • 如果是对象,则调用对象的valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用对象的toString()方法,然后再依次按照前面的规则转换返回的字符串值。

console.log(Number('')) //
console.log(Number('a')) //NaN
console.log(Number(true)) //
console.log(Number('001')) //
console.log(Number('001.1')) //1.1
console.log(Number('0xf')) //
console.log(Number('000xf')) //NaN var a = {} // 调用对象的valueOf()方法
console.log(Number(a)) //NaN
a.toString = function () {
return 2
} // 重写valueOf()方法
console.log(Number(a)) //
a.valueOf = function () {
return 1
}
console.log(Number(a)) //

parseInt():

常常用于将其它类型值转化为整形。parseInt转换与Number()有区别,具体规则如下:

  • parseInt(value,radius)有两个参数,第一个参数是需要转换的值,第二个参数是转换进制(该值介于 2 ~ 36 之间。如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。),如果不传(或值为0),默认以10为基数(如果value以 “0x” 或 “0X” 开头,将以 16 为基数)

  • 注意在第二个参数默认的情况下,如果需要转换的string值以0开头,如'070',有一些环境中,会自动转化为8进制56,有一些环境中会自动转化为10进制70。所以为了统一效果,我们在转换为10进制时,会将第二个参数传10

console.log(parseInt('')) //NaN
console.log(parseInt('a')) //NaN
console.log(parseInt('1234blue')) //
console.log(parseInt(true)) //NaN
console.log(parseInt('070')) //70,但是有一些环境中会自动转换为8进制56
console.log(parseInt('070', 8)) //
console.log(parseInt('001.1')) //
console.log(parseInt('0xf')) //15,16进制
console.log(parseInt('AF', 16)) //175,16进制
console.log(parseInt('AF')) //NaN
console.log(parseInt('000xf')) // var a = {}
console.log(parseInt(a)) //NaN
a.toString = function () {
return 2
} // 重写valueOf()方法
console.log(parseInt(a)) //
a.valueOf = function () {
return 1
} // 重写valueOf()方法
console.log(parseInt(a)) //

parseFloat():

parseFloat()转换规则基本与parseInt()一致,只有如下不同点

  • parseFloat()遇到浮动数据时,浮点有效(但是只有第一个.有效),如"10.1"会被转为10.1;'10.1.1'会被转为10.1

  • parseFloat()只会默认处理为10进制,而且会忽略字符串前面的0,所以不会有在默认情况下转为8进制的情

console.log(parseFloat('1234blue')) //
console.log(parseFloat('1234blue', 2)) //
console.log(parseFloat('0xA')) //
console.log(parseFloat('10.1')) //10.1
console.log(parseFloat('10.1.1')) //10.1
console.log(parseFloat('010')) //

由于Number()函数在转换字符串时比较复杂而且不够合理,因此在处理整数的时候更常用的是parseInt()函数-需注意最好第二个参数传10,处理浮点数时更常用parseFloat()

另外注意,浮点数直接的计算存在误差,所以两个浮点数无法用"="进行判断

var a = 10.2
var b = 10.1
console.log(a - b === 0.1) //false
console.log(a - 10.1 === 0.1) //false,实际是0.09999999999999964
console.log(a - 0.1 === 10.1) //true

 

string字符串:

要把一个值转换为一个字符串有三种方式。

  • 第一种是使用几乎每个值都有的toString(基数)方法(除去null和undefined没有)——当需要toString的值为number时,参数可以生效。

  • 第二种是隐式转换,+ 号:要转换的值为对象时,回调用对象的valueOf属性。

  • 第三种是通过转换函数String(),转换规则如下

    • 如果值有toString()方法,则调用该方法(没有参数)并返回相应的结果,(注意不会调用valueOf()方法)

    • 如果值是null,则返回null,如果值是undefined,则返回undefined

var c = {};
console.log(c);//[object Object]
console.log(c + '1');//[object Object]1
console.log(String(c));//[object Object] c.valueOf = function () { return '重写c的valueOf方法' };
console.log(c);// {valueOf: ƒ} valueOf重写
console.log(c + '1');// 重写c的valueOf方法1 隐式转换时,valueOf起作用了 console.log(String(c));// [object Object]
c.toString = function () { return '重写c的toString方法' };
console.log(c);// {valueOf: ƒ, toString: ƒ} toString起作用了
console.log(String(c)); // 重写c的toString方法 console.log(String(null));// null,null和undefined可以String()输出
console.log(String(undefined));// undefined ,null和undefined可以String()输出
// console.log(null.toString());//报错,null和undefined不能toString let d = {}
d.valueOf = function () {
console.log('valueOf 执行了')
return 'valueOf'
};
d.toString = function () {
console.log('toString 执行了')
return 'toString'
};
console.log(d + '1') // 隐式转换 valueOf(转换为原始值) 执行了
console.log(String(d)) // String toString(获得该值的字符串表示法) 执行了

object类型:

Object的每个实例都具有下列属性和方法:

  • constructor——保存着用于创建当前对象的函数

  • hasOwnProperty(propertyName)——用于检查给定的属性在当前对象实例中(而不是在实例的原型中)是否存在。其中,作为参数的属性名(propertyName)必须以字符串形式指定(例如:o.hasOwnProperty("name")

  • isPrototypeOf(object)——用于检查传入的对象是否是另一个对象的原型

  • propertyIsEnumerable(propertyName)——用于检查给定的属性是否能够使用for-in语句来枚举

  • toString()——返回对象的字符串表示

  • valueOf()——返回对象的字符串、数值或布尔值表示。

var obj = new Object();
obj.name = 'zs';
obj.sayHi = function () {
console.log('Hi');
}
console.log(obj.hasOwnProperty('a')); // 实例对象 true
console.log(obj.hasOwnProperty('sayHi')); // 实例对象 true
console.log(obj); // 实例对象
console.log(obj.constructor); // 构造函数Object()
console.log(obj.__proto__); // 原型

valueOf()toString()

  • valueOf方法返回指定对象的原始值。

  • toString: 返回对象的字符串表示

valueOf转换规则

MDN对valueOf()的描述

JavaScript调用valueOf方法将对象转换为原始值。你很少需要自己调用valueOf方法;当遇到要预期的原始值的对象时,JavaScript会自动调用它。

默认情况下,valueOf方法由 Object 后面的每个对象继承。 每个内置的核心对象都会覆盖此方法以返回适当的值。如果对象没有原始值,则valueOf将返回对象本身。

JavaScript的许多内置对象都重写了该函数,以实现更适合自身的功能需要。因此,不同类型对象的valueOf()方法的返回值和返回值类型均可能不同。

非原始值(也就是对象)重写规则如下:

对象 valueOf返回值
Array 数组本身
Boolean 布尔值
Date 返回毫秒形式的时间戳
Function 函数本身
Number 数字值
Object 对象本身
String 字符串值
// Array:返回数组对象本身
var array = ["ABC", true, 12, -5];
console.log(array.valueOf() === array); // true // Date:当前时间距1970年1月1日午夜的毫秒数
var date = new Date(2013, 7, 18, 23, 11, 59, 230);
console.log(date.valueOf()); // // Number:返回数字值
var num = 15.26540;
console.log(num.valueOf()); // 15.2654 // 布尔:返回布尔值true或false
var bool = true;
console.log(bool.valueOf() === bool); // true // new一个Boolean对象
var newBool = new Boolean(true);
// valueOf()返回的是true,两者的值相等
console.log(newBool.valueOf() == newBool); // true
// 但是不全等,两者类型不相等,前者是boolean类型,后者是object类型
console.log(newBool.valueOf() === newBool); // false // Function:返回函数本身
function foo(){}
console.log( foo.valueOf() === foo ); // true
var foo2 = new Function("x", "y", "return x + y;");
console.log( foo2.valueOf() );
/*
ƒ anonymous(x,y) {return x + y;}
*/ // Object:返回对象本身
var obj = {name: "张三", age: 18};
console.log( obj.valueOf() === obj ); // true // String:返回字符串值
var str = "http://www.xyz.com";
console.log( str.valueOf() === str ); // true // new一个字符串对象
var str2 = new String("http://www.xyz.com");
// 两者的值相等,但不全等,因为类型不同,前者为string类型,后者为object类型
console.log( str2.valueOf() === str2 ); // false

对象转换为布尔值

  1. 直接转换为true(包装类型也一样),不调用valueOf和toString

// 保存原始的valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString; // 添加valueOf日志
Object.prototype.valueOf = function () {
console.log('valueOf');
return valueOf.call(this);
};
// 添加toString日志
Object.prototype.toString = function () {
console.log('toString');
return toString.call(this);
};
var a = {};
var b = new Boolean(false); if (a) {
console.log(1);
}
if (b) {
console.log(2);
}

对象转换为数字

对象转换为数字会依次调用valueOf和toString方法,具体规则如下:

  1. 如果对象具有valueOf方法且返回原始值(string、number、boolean、undefined、null),则将该原始值转换为数字(转换失败会返回NaN),并返回这个数字

  2. 如果对象具有toString方法且返回原始值(string、number、boolean、undefined、null),则将该原始值转换为数字(转换失败会返回NaN),并返回这个数字

  3. 转换失败,抛出TypeError

// 保存原始的valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString; // 添加valueOf日志
Object.prototype.valueOf = function () {
console.log('valueOf');
return valueOf.call(this);
};
// 添加toString日志
Object.prototype.toString = function () {
console.log('toString');
return toString.call(this);
};
var a = {};
console.log(++a); // valueOf toString NaN
  1. valueOf方法返回的是对象本身,不是原始值,继续执行

  2. toString方法返回的是"[object Object]",是原始值(字符串),将字符串转换为数字NaN

// 保存原始的valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString; // 添加valueOf日志
Object.prototype.valueOf = function () {
console.log('valueOf');
return "1"; // 强制返回原始值
};
// 添加toString日志
Object.prototype.toString = function () {
console.log('toString');
return toString.call(this);
};
var a = {};
console.log(++a); // valueOf 2

分析:valueOf返回原始值(字符串),直接将该字符串转换为数字,得到1

对象转换为字符串

对象转换为数字会依次调用toStringvalueOf方法,具体规则如下:

  1. 如果对象具有toString方法且返回原始值(string、number、boolean、undefined、null),则将该原始值转换为字符串,并返回该字符串

  2. 如果对象具有valueOf方法且返回原始值(string、number、boolean、undefined、null),则将该原始值转换为字符串,并返回该字符串

  3. 转换失败,抛出TypeError

// 保存原始的valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString; // 添加valueOf日志
Object.prototype.valueOf = function () {
console.log('valueOf');
return valueOf.call(this);
};
// 添加toString日志
Object.prototype.toString = function () {
console.log('toString');
return toString.call(this); // '[object Object]' toString方法先调用 ,如果返回结果是字符串,则停止调用 valueOf,不是字符串,那么就调用 valueOf
};
var a = {};
console.log(a.toString()); // valueOf toString [object Object]str
// alert(a) // alert主动调用toString方法,返回了字符串"[object Object]",对象最终转换为该字符串
// 保存原始的valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString; // 添加valueOf日志
Object.prototype.valueOf = function () {
console.log('valueOf');
return valueOf.call(this);
};
// 添加toString日志
Object.prototype.toString = function () {
console.log('toString');
return this;
};
var a = {};
alert(a);
/*
toString
valueOf
Uncaught TypeError: Cannot convert object to primitive value
at 1.js:16
*/

toString转换规则

对象 toString返回值
Array 以逗号分割的字符串,如[1,2]的toString返回值为"1,2",跳过null,undefined
Boolean "True"
Date 可读的时间字符串,如"Tue Oct 15 2019 12:20:56 GMT+0800 (中国标准时间)"
Function 声明函数的JS源代码字符串
Number "数字值"
Object "[object Object]"
String "字符串"

强制类型转换

Number强制转换对象

let a = { name: 123 };
console.log(Number(a)); // NaN
/*
* JS对象强制类型转换
* 主要调用 object.valueOf() 和 object.toString() 方法
* 1.先调用 object 的 valueOf() 方法
* 2.判断返回值 是否为 基础数据类型?
* 3.是!则转换规则按照相应数据类型的规则对其进行转换
* 4.不是!在返回值的基础上继续调用 toString() 方法
* 5.判断调用 toString() 方法返回值是否为 基础数据类型
* 6.是!则转换规则按照相应数据类型的规则对其进行转换
* 7.不是!报错:
* */

现在我们用自定义方法覆盖toString()方法:

a.toString = function () {return {name: 'newName'}} // 让toString方法返回值为 复杂数据类型
a.toString() // 调用覆盖的方法
Number(a) // 报错

现在验证让toString()方法返回值为 基础数据类型

a.toString = function () {return '321'} // 让toString方法返回值为 复杂数据类型
a.toString() // 调用覆盖的方法
Number(a) //

所以Number强制转换对象的过程即为如上7步

对象String()转换字符串

/* 1.先调用对象的toString方法
2.判断该方法的返回值是否为基础数据类型(Number,String,Boolean,Undefined,ull)
3.若返回值为基础数据类型,则转换规则按照相应数据类型的转换规则对其进行转换
4.若返回值不为基础数据类型,则在该返回值的基础上继续调用valueOf方法
5.判断valueOf的返回值是否为基础数据类型
6.判断是否为基础数据类型,若是基础数据类型则进行操作3
7.若仍旧不为基础数据类型则报错 */ let b = {name: 'houfee'}
console.log(String(b)); // [object Object]
let c = []
console.log(String(c)); // 空字符串
let d = {}
console.log(String(d)); // [object Object]

String与Number的区别则在于

  • Number是先调用valueOf()再调用toString ()

  • 而String是先调用toString()再调用valueOf()

Number()先转换为原始类型,再转化为字符串形式

String()先转换为字符串形式,再转化为原始类型

判断数据类型

function isArray(value) {
return Object.prototype.toString.call(value) == "[object Array]"
}
function isFunction(value) {
return Object.prototype.toString.call(value) == "[object Function]"
}
function isRegExp(value) {
return Object.prototype.toString.call(value) == "[object RegExp]"
}

面试题

console.log({}); // {}
console.log(Number({})); // NaN、
console.log(String({})); // [object Object]
console.log(Boolean({})); // true console.log([]); // []
console.log(Number([])); //
console.log(String([])); // 空字符串
console.log(Boolean([])); // true console.log({} + {}) // [object Object][object Object]
console.log({} + []) // [object Object]
console.log([] + {}) // [object Object]
console.log([] + []) // 空字符串

JS高级学习笔记(1)- 数据类型及转换规则的更多相关文章

  1. 转:JS高级学习笔记(8)- JavaScript执行上下文和执行栈

    必看参考: 请移步:博客园 JavaScript的执行上下文 深入理解JavaScript执行上下文和执行栈 JavaScript 深入之执行上下文 写在开头 入坑前端已经 13 个月了,不能再称自己 ...

  2. JS高级学习笔记(6)- 事件循环

    参考文章:深入理解JS引擎的执行机制        JavaScript 异步.栈.事件循环.任务队列 我的笔记:ES系列之Promise async 和 await Event Loop 前提 js ...

  3. JS高级学习笔记(9) 之 转:前端路由跳转基本原理

    原文链接: 前端路由跳转基本原理 前述 前端三大框架Angular.React和Vue都推行单页面应用SPA开发模式,这是因为在路由切换时,替换DOM Tree中发生修改的DOM部分,来减少原来因为多 ...

  4. JS高级学习笔记(10) 之 js 时怎么解析HTML标签的

    DOM 节点类型 浏览器渲染过程 浏览器是怎么把HTML标签语言和JavaScript联系在一起的,这就是我们常说的DOM. 浏览器中的DOM解析器把HTML翻译成对象(object),然后JavaS ...

  5. JS高级学习笔记(2)之js多线程

    参考大神:Javascript多线程 web worker ---- 6.Web Worker 概述 截图过来: 线程之间的通信 let worker = new Worker(‘js文件路径’) 主 ...

  6. js再学习笔记

    #js再学习笔记 ##基本 1.js严格区分大小写   2.js末尾的分号可加,也可不加   3.六种数据类型(使用typeof来检验数据的类型) `typeof` - undefined: `var ...

  7. Python高级学习笔记

    Python高级学习笔记,此笔记中包含Linux操作系统.Html+CSS+JS.网络协议等. 所有思维导图为本人亲手所画,请勿用于商用. 大哥们,求点赞哦. 第一天笔记:链接 第二天笔记:链接 第三 ...

  8. js高级程序设计笔记之-addEventListener()与removeEventListener(),事件解除与绑定

    js高级程序设计笔记之-addEventListener()与removeEventListener(),事件解除与绑定 addEventListener()与removeEventListener( ...

  9. JS数组学习笔记

    原文:JS数组学习笔记 最近在备课数组,发现很多ES5的方法平时很少用到.细节比较多,自己做了大量例子和整理,希望对大家了解JavaScript中的Array有所帮助. 概念 数组是值的有序集合.每个 ...

随机推荐

  1. 一文解读CDN (转)

    如今这个移动互联网时代,越来越多的人使用手机观看视频,丰富自己的娱乐生活. 可是,大家在追剧的时候,有没有想过一个问题——为什么有时候明明自己手机的网速很快,但观看视频时,仍然卡顿? 回答这个问题之前 ...

  2. Python学习笔记之正则表达式

    本篇在写的时候大量参考了https://deerchao.cn/tutorials/regex/regex.htm的内容 一.什么是正则表达式 在编写处理字符串的程序或网页时,经常会有查找符合某些复杂 ...

  3. C++中%d,%s,%x,%f,%.100f,%的意思

    C++中%d,%s,%x,%f,%.100f,%的意思 标准格式化输出:格式字符有d,o,x,u,c,s,f,e,g等. 格式说明:由“%”和格式字符组成,如%d.%f等. %c用来输出一个字符; % ...

  4. VOC2012数据集提取自己需要的类的图片和对应的xml标签

    根据需要修改路径和自己需要的类即可. import os import os.path import shutil fileDir_ann = r'/home/somnus/tttt/VOC2012/ ...

  5. python学习第二课——while循环

    #while循环基础语句 while 1==1: print('OK') #死循环 #如何阻止死循环 count=0 while count<10: print('第'+(str)(count) ...

  6. 一、iBatis进行分页查询

    1.ibatis理解: iBatis属于半自动化的ORM框架,我们需要编写SQL语句,由iBatis进行数据库访问,返回结果.而iBatis可以为我们做的更多,比如对查询参数集合.结果.分页查询.事务 ...

  7. SystemVerilog Assertion 设计、调试、测试总结(1)

    暑期实习两个月的其中一个任务是:如何在设计中加入断言?以及断言的基本语法.三种应用场景下的断言(如FIFO.FSM.AXI4-lite总线).参考书籍:<System Verilog Asser ...

  8. 深度学习Tensorflow框架的安装

    选择下载安装Anaconda3.4.2.0-python3.5版本安装(3.6版本不适合后面opencv-python的安装): 打开Anaconda Prompt命令窗口编辑界面(黑窗口),输入py ...

  9. dotnet-千星项目OpenAuthNet基于NetCore21的快速开发框架

    下载

  10. django+centos+mariadb读写分离完美实现(上)-mysql主从备份实现

    首先画图一张,用来展示今天要做的事情,读写分离,个人理解就是使用mysql主从备份的原理,让两个数据库同时为自己提供服务.其中主库负责数据保存,从库负责数据展示,可以一主一从,也可以一主多从.从而降低 ...