原文:Object-to-Primitive Conversions in JavaScript

对象转化为基础数据类型,其实最终都是用调用对象自带的valueOf和toString两个方法之一并获得其返回值,作为其基础数据类型。

基础数据类型包括这么几种:null, undefined, number, boolean, string

内部实现机制

但是什么时候调用valueOf,什么时候调用toString,却困惑了很长一段时间。

var obj = {
toString: function () {
return 'test';
}
}

以alert(obj)为例,我们知道,alert(obj)会优先调用obj的toString方法,其内部实现机制是这样的:

  1. alert调用该引用的GetValue方法,返回它所指向的对象
  2. alert该值的基础上调用toString方法(这个跟对象的toString方法不同)
  3. toString在该值上调用toPrimitive方法,传递hint参数为string(是toPrimitive方法的一个参数)
  4. toPrimitive调用对象的内部方法[[DefaultValue]],并传递hint参数为string
  5. [[DefaultValue]]调用对象(obj)的toString方法,并把this指向该对象
  6. toString的结果是一个基本数据类型,返回该值
  7. 结果是一个字符串类型,将其返回该alert
  8. alert展现这个值

我们注意到,最开始的GetValue和toString其实是alert调用的方法,对象转化的核心方法其实是toPrimitive,这个方法获取一个任意值,并返回一个基础数据类型,如果传入的参数不是一个基础数据类型,将会调用对象内部的 [[DefaultValue]]方法获取其default value(默认值)。

[[DefaultValue]]是每个对象都有的一个内部方法,这个方法可以接收一个形参hint,这个形参的值要么是string,要么是number,如果为空,则默认为number,除非该对象是Date,Date的该方法默认传入的是string(作者说这很愚蠢)。之后会决定是调用对象的toString方法还是调用对象的valueOf方法。如果hint是number,则优先调用valueOf方法,否则优先调用toString方法。

具体过程如下(我们把优先调用的方法叫做方法一):

  1. 如果方法一存在,而且可以被调用,则调用它获取结果,否则跳到第3步
  2. 如果1的结果是基本类型,返回它
  3. 如果方法二存在,而且可以被调用,则调用它获取结果,否则跳到第5步
  4. 如果第三步的结果是基础数据类型,返回它
  5. 抛出TypeError异常

也就是说,toPrimitive方法返回的一定是一个基本数据类型,否则就抛出类型错误异常

对于加操作的困惑

var foo = {
toString: function () {
return "foo";
},
valueOf: function () {
return 5;
}
}; alert(foo + "bar"); // 5bar
alert([foo, "bar"].join("")); // foobar

在这个操作中,加操作并没有像我们理所当然的想法那样调用toString方法,获取字符串,反而是调用了valueOf,然后进行字符串组合,这不是我们想要的,但是它确实是这样的。

注:以前我的想法更荒谬,我以为对象会根据基本数据类型进行转化,比如obj + 5,我以为会在obj转化为基本数据类型的过程中同时会将该值转化为数字……

要理解该过程,就该理解加操作的计算过程:

  1. 计算加号左边,获取其值
  2. 计算加号右边,获取其值
  3. 两边同时调用toPrimitive方法,hint参数为空
  4. 如果任意一个类型为string,跳到第7步
  5. 将两个值转化为数字(调用ToNumber)
  6. 返回两个值之和
  7. 将两个值转化为字符串(调用ToString)
  8. 返回两个值的组合

可以看到,hint参数为空,而如果对象不是Date对象,则hint默认为number,即调用toString方法

javascript对象转化为基本数据类型规则的更多相关文章

  1. js中对象转化成字符串、数字或布尔值的转化规则

    js中对象可以转化成 字符串.数字.布尔值 一.对象转化成字符串: 规则: 1.如果对象有toString方法,则调用该方法,并返回相应的结果:(代码通常会执行到这,因为在所有对象中都有toStrin ...

  2. 15条规则解析JavaScript对象布局(__proto__、prototype、constructor)

    大家都说JavaScript的属性多,记不过来,各种结构复杂不易了解.确实JS是一门入门快提高难的语言,但是也有其他办法可以辅助记忆.下面就来讨论一下JS的一大难点-对象布局,究竟设计JS这门语言的人 ...

  3. javascript--15条规则解析JavaScript对象布局(__proto__、prototype、constructor)

    大家都说JavaScript的属性多,记不过来,各种结构复杂不易了解.确实JS是一门入门快提高难的语言,但是也有其他办法可以辅助记忆.下面就来讨论一下JS的一大难点-对象布局,究竟设计JS这门语言的人 ...

  4. JavaScript中对象转换为原始值的规则

    JavaScript中对象转换为原始值遵循哪些原则? P52 对象到布尔值对象到布尔值的转换非常简单:所有的对象(包括数字和函数)都转换为true.对于包装对象亦是如此:new Boolean(fal ...

  5. 第六章:Javascript对象

    对象是javascript的基本数据类型.对象是一种复合值.它将很多值(原始值 或者其他对象)聚合在一起.可通过名字访问这些值.对象也可以看做是属性的无序集合,每个属性都有一个名/值.属性名是字符串, ...

  6. JavaScript对象(来自百度知道)

    JavaScript中对象的创建有以下几种方式: (1)使用内置对象(2)使用JSON符号(3)自定义对象构造 一.使用内置对象 JavaScript可用的内置对象可分为两种:1,JavaScript ...

  7. Javascript对象基础讲解

    1.Object对象详解 javascript 里最基本的数据类型是对象. avaScript里的对象其实是一个无序的属性集合,属性又是一个个的名-值对. 除了字符串,数字,true,false,nu ...

  8. 深入理解javascript对象系列第二篇——属性操作

    × 目录 [1]查询 [2]设置 [3]删除[4]继承 前面的话 对于对象来说,属性操作是绕不开的话题.类似于“增删改查”的基本操作,属性操作分为属性查询.属性设置.属性删除,还包括属性继承.本文是对 ...

  9. 第一百零七节,JavaScript基本包装类型,数据类型的方法

    JavaScript基本包装类型,数据类型的方法 学习要点: 1.基本包装类型概述 2.Boolean类型 3.Number类型 4.String类型 为了便于操作基本类型值,ECMAScript提供 ...

随机推荐

  1. AngularJS开发指南10:AngularJS依赖注入的详解

    依赖注入是一种软件设计模式,用来处理代码的依赖关系. 一般来说有三种方法让函数获得它需要的依赖: 它的依赖是能被创建的,一般用new操作符就行. 能够通过全局变量查找依赖. 依赖能在需要时被导入. 前 ...

  2. “耐撕”团队 2016.03.30 站立会议

    1. 时间: 16:45--17:05  总计:20分钟 2. 成员: Z 郑蕊 * 组长 (博客:http://www.cnblogs.com/zhengrui0452/), P 濮成林(博客:ht ...

  3. hdu4287 字典树

    #include<stdio.h> #include<string.h> #include<stdlib.h> #define maxn 10 struct tri ...

  4. du 命令

    Linux du命令也是查看使用空间的,但是与df命令不同的是Linux du命令是对文件和目录磁盘使用的空间的查看,还是和df命令有一些区别的. 1.命令格式: du [选项][文件] 2.命令功能 ...

  5. awk多文件操作

    awk 多文件操作2种实现方法 我们经常会将2个有关联文本文件进行合并处理.分别从不同文件获取需要的列,然后, 整体输出到一起.awk进行多文件处理时候,常常会遇到2个方面问题,第一个是怎么样合并多个 ...

  6. Shell good example

    (1) Source code #! /bin/bash reference ()     {     pa=\$"$1"     echo $pa     x=`eval &qu ...

  7. web前端开发常用的10个高端CSS UI开源框架

    web前端开发常用的10个高端CSS UI开源框架   随着人们对体验的极致追求,web页面设计也面临着新的挑战,不仅需要更人性化的设计理念,还需要设计出更酷炫的页面.作为web前端开发人员,运用开源 ...

  8. SVN 服务器端安装过程

    1.安装软件版本: VisualSVN-Server-2.1.5.msi 右击安装软件,单机“安装” 2.单击[Next] 选择“I accept the terms in the License A ...

  9. CODEVS1995 || TYVJ1863 黑魔法师之门

    P1863 [Poetize I]黑魔法师之门 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 经过了16个工作日的紧张忙碌,未来的人类终于收集到了足够的能源 ...

  10. LABJS使用教程

    知道LABJS这个概念其实早于sea.js,但因为sea.js是中文,并且第一眼就喜欢上sea.js的CommonJS所以并没有深入了解过LABJS. 在使用sea.js的时候不可避免的碰到js文件依 ...