• javascript对象转化为基本数据类型规则


    原文: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方法

  • 相关阅读:
    Padding和父子继承宽高之间的关系
    Js实例——模态框弹出层
    Java——异常谜题
    BZOJ 2743 【HEOI2012】 采花
    BZOJ 4614 【WF2016】 Oil
    BZOJ 1004 【HNOI2008】 Cards
    codevs 2495 水叮当的舞步
    BZOJ 1227 【SDOI2009】 虔诚的墓主人
    BZOJ 3505 【CQOI2014】 数三角形
    BZOJ 4423 【AMPPZ2013】 Bytehattan
  • 原文地址:https://www.cnblogs.com/strayling/p/3752795.html
Copyright © 2020-2023  润新知