0

0

详解ECMAScript7规范中ToPrimitive抽象操作的知识(示例)

不言

不言

发布时间:2018-09-17 14:53:07

|

4980人浏览过

|

来源于php中文网

原创

本篇文章给大家带来的内容是关于ecmascript7规范中toprimitive抽象操作的详细解析(示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

本文将介绍ECMAScript7规范中的ToPrimitive抽象操作。

预备知识

ECMAScript数据类型

ECMAScript数据类型细分为两大类数据类型,一种是语言类型,一种是规范类型:

语言类型是可以直接被开发人员使用的数据类型;

规范类型代表meta-values(元值),用在算法中描述ECMAScript语言结构和语言类型的语义。它们主要用于规范的说明,不需要被真正地实现。

ECMAScript的语言类型一共有7种:

Undefined

Null

Boolean,布尔类型

String,字符串类型

Symbol,符号类型

Number,数字类型

Object,对象类型

原始数据类型是上述Undefined、Null、Boolean、String、Symbol和Number的统称,也就是非对象数据类型。
下文涉及到的规范类型只有List,也就是列表,类似于数组,用符号« »表示。

@@toPrimitive

Symbol有很多有名的符号,比如@@toPrimitive,也就是Symbol.toPrimitive,这是定义在Symbol对象上的一个属性。

ToPrimitive(input [, PreferredType])

该抽象操作接受一个参数input和一个可选的参数PreferredType。该抽象操作的目的是把参数input转化为非对象数据类型,也就是原始数据类型。如果input可以同时转化为多个原始数据,那么会优先参考PreferredType的值。转化过程参照下表:

参数input的数据类型 结果
Undefined 返回input自身
Null 返回input自身
Boolean 返回input自身
Number 返回input自身
String 返回input自身
Symbol 返回input自身
Object 执行下面的步骤

如果input的数据类型是对象,执行下述步骤:

1、如果没有传入PreferredType参数,让hint等于"default";

2、如果PreferredType是hint String,让hint等于"string";

3、如果PreferredType是hint Number,让hint等于"number";

4、让exoticToPrim等于GetMethod(input, @@toPrimitive),大概语义就是获取参数input的@@toPrimitive方法;

5、如果exoticToPrim不是Undefined,那么:

让result等于Call(exoticToPrim, input, « hint »),大概语义就是执行exoticToPrim(hint);

如果result是原始数据类型,返回result;

抛出类型错误的异常;

6、如果hint是"default",让hint等于"number";

7、返回OrdinaryToPrimitive(input, hint)抽象操作的结果。

OrdinaryToPrimitive(O, hint)

O的数据类型是对象,hint的数据类型是字符串,并且hint的值要么是"string",要么是"number"。该抽象操作的步骤如下:

WPS AI
WPS AI

金山办公发布的AI办公应用,提供智能文档写作、阅读理解和问答、智能人机交互的能力。

下载

1、如果hint是"string",让methodNames等于« "toString", "valueOf" »;

2、如果hint是"number",让methodNames等于« "valueOf", "toString" »;

3、按顺序迭代列表methodNames,对于每一个迭代值name:

让method等于Call(method, O),大概语义就是执行method();

如果result的类型不是对象,返回result;

让method等于Get(O, name),大概语义就是获取对象O的name值对应的属性;

如果method可以调用,那么:

4、抛出类型错误的异常。

由上述操作步骤可知:

通过ToPrimitive的步骤6可知,当没有提供可选参数PreferredType的时候,hint会默认为"number";

通过ToPrimitive的步骤4可知,可以通过定义@@toPrimitive方法来覆盖默认行为,比如规范中定义的Date日期对象和Symbol符号对象都在原型上定义了@@toPrimitive方法。

实践

可能有人会问,为什么要讲解规范中的抽象方法,抽象方法我又用不到。其实不然,这个方法在很多地方都会用到,只是你不知道罢了。下面通过讲解几个实例让大家加深对它的理解。

'' + [1, 2, 3]

'' + [1, 2, 3] // "1,2,3"

根据规范中的加法操作,对于操作x + y,会调用ToPrimitive(x)和ToPrimitive(y)把x和y转化为原始数据类型。上面的例子中''本身就是原始数据类型了,所以返回''自身。[1, 2, 3]是对象类型,并且数组没有定义@@toPrimitive属性。因为没有提供PreferredType,所以在ToPrimitive操作的步骤6中,hint变为"number",所以OrdinaryToPrimitive中的methodNames是« "valueOf", "toString" »。

var a = [1, 2, 3]
a.valueOf() // [1, 2, 3],数组a本身
a.toString() // "1,2,3"

因为valueOf返回的是数组a本身,还是对象类型,所以会继续调用toString方法,返回了字符串"1,2,3",所以

'' + [1, 2, 3] // => '' + '1,2,3' => '1,2,3'

那么,如果我们覆盖数组原型上的valueOf方法,使得该方法返回一个原始数据类型,那么结果会是什么呢?

var a = [1, 2, 3]
a.valueOf = function () {
    console.log('trigger valueOf')
    return 'hello'
}
'' + a //  => '' + 'hello' => 'hello'

覆盖默认的valueOf之后,调用valueOf会返回原始数据类型。根据OrdinaryToPrimitive的3.2.2,这个时候就直接返回了,不会再调用toString方法。同时在控制台会log出"trigger valueOf",也就是说valueOf确实是调用了。
那么,如果我们覆盖数组默认的toString方法,使得该方法返回对象类型,那么结果会是什么呢?

var a = [1, 2, 3]
a.toString = function () {
    console.log('trigger toString')
    return this
}
'' + a // Uncaught TypeError: Cannot convert object to primitive value

因为数组原型上的valueOf方法返回对象类型,在上面的例子中,我们把toString覆盖了,使它也返回对象类型,那么就会直接走到OrdinaryToPrimitive的第4步,也就是抛出类型错误的异常,不能把对象转化为原始数据类型。
在上面我们提到过可以通过@@toPrimitive方法来自定义ToPrimitive的行为,比如下面的例子:

var a = [1, 2, 3]
a[Symbol.toPrimitive] = function () {
    return 'custom'
}
'' + a // => '' + 'custom' => 'custom'

相加操作在调用ToPrimitive的时候没有提供PreferredType,接下来讲一个会优先使用hint String作为PreferredType的例子:

var a = [1, 2, 3]
a.valueOf = function () {
    console.log('trigger valueOf')
    return 'hello'
}
a.valueOf() // "hello"
a.toString() // "1,2,3"
var obj = {}
obj[a] = 'hello' // obj是{1,2,3: "hello"}

在把变量作为键值使用的时候,会调用ToPrimitive把键值转化为原始数据类型,并且PreferredType的值是hint String。通过上面的例子也可以看出来,a.valueOf和a.toString的结果都是字符串,但是使用了'1,2,3',也就是使用了a.toString的结果。当然,如果我们重新定义toString方法,并且返回对象,那么就会使用valueOf的值了:

var a = [1, 2, 3]
a.valueOf = function () {
    console.log('trigger valueOf')
    return 'hello'
}
a.toString = function () {
    console.log('trigger toString')
    return this
}
var obj = {}
obj[a] = 'hello' // obj是{hello: "hello"}

并且会在控制台先log出"trigger toString",后log出"trigger valueOf"。当然,如果这两个都返回对象,那么还是会报错:

var a = [1, 2, 3] // 使用原型链上的valueOf方法
a.toString = function () {
    console.log('trigger toString')
    return this
}
var obj = {}
obj[a] = 'hello' // Uncaught TypeError: Cannot convert object to primitive value

Date

在上面讲ToPrimitive的时候,提到Date对象和Symbol对象在原型上定义了@@toPrimitive方法。在ToPrimitive的第6步的操作中,我们可以看到当没有提供PreferredType的时候,优先调用valueOf方法。Date原型上的@@toPrimitive做的事情非常简单:当没有提供PreferredType的时候,优先调用toString方法。所以对于上面的操作,Date对象的行为是不一样的:

var a = [1, 2, 3]
a.valueOf = function () {
    return 'hello'
}
a.valueOf() // "hello"
a.toString() // "1,2,3"
'' + a // "hello"
var date = new Date()
date.valueOf() // 1536416960724
date.toString() // "Sat Sep 08 2018 22:29:20 GMT+0800 (中国标准时间)"
'' + date // "Sat Sep 08 2018 22:29:20 GMT+0800 (中国标准时间)"

我们可以看到date的valueOf方法和toString方法都返回原始数据类型,但是优先使用了toString方法。

总结

本文主要讲解了ToPrimitive抽象操作,以及一些相关的例子,希望大家能有所收获。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

7

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

7

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

1

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

1

2026.01.30

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

20

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

16

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

18

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

3

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.3万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.5万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号