ES6学习——新的语法:Symbols——Symbol.toPrimitive,Symbol.hasInstance,Symbol.toStringTag,Symbol.species
来源:互联网 发布:java工程师简历范文 编辑:程序博客网 时间:2024/06/05 10:39
这节讲的这四个没有Symbol.iterator常见,但可能也会用到,由于浏览器对这些well-known symbols不是都支持,所以我们需要用Kinoma来测试这些特性。
先看比较简单的Symbol.toStringTag:
function Obj(){}Obj.prototype[Symbol.toStringTag] = "-Obj-";let o1 = new Obj(),o2 = new Obj();;trace(o1+"\n");//[object -Obj-]o2[Symbol.toStringTag] = "-o2-Obj-";trace(o2+"\n");//[object -o2-Obj-]trace({} + "\n");//[object Object]trace(Object.prototype.toString.call(o1)+"\n");//[object -Obj-]trace(Object.prototype.toString.call(o2)+"\n");//[object -o2-Obj-]trace(Object.prototype.toString.call({})+"\n");//[object Object]通过上面的代码,可以看到ES6中对检测对象类型提供更灵活的特性,不在所有对象都是[object Object]了,你自己可以自定义。
接着Symbol.hasInstance,这个symbol是用来控制instanceof操作符的,关于instanceof的详细讲解,请参考这里
看个例子:
function Circle(r){this.r = r;}Circle[Symbol.hasInstance] = function(inst){return inst.r >= 0 && inst.r <= 10;//半径在0-10之内的我们才认为是个圆}var c1 = new Circle(5),c2 = new Circle(10),c3 = new Circle(15);trace((c1 instanceof Circle) + "\n");//truetrace((c2 instanceof Circle) + "\n");//truetrace((c3 instanceof Circle) + "\n");//false
这里需要仔细看,这个symbol需要定义在Circle上,而不是Circle的prototype上。在ES5以后也可以用Object.defineProperty来搞定:
Object.defineProperty( Circle, Symbol.hasInstance, { value: function(inst) { return inst.r >= 0 && inst.r <= 10; }} );
在来看Symbol.species,这个接口比较有意思,不太好解释。是这样的,我们在使用Array的一些方法时,比如map,slice会返回一个新的数组,这个过程大家可能认为是理所当然的,但实际上返回的结果是可以控制的,通过的就是Symbol.species,实际写代码中,估计用到这个symbol的机会可能真不多。
下面看个例子:
class MyArray1 extends Array {static get [Symbol.species]() { return Array;}}class MyArray2 extends Array {}let result1 = new MyArray1().map(x => x);trace(result1 instanceof Array); // truelet result2 = new MyArray2().map(x => x);trace(result2 instanceof MyArray2); // true在ES6中,内置类都是可以继承的,在MyArray1中覆盖了Symbol.species实现,返回了Array,所以map出来的新数组是Array类型而不是MyArray类型。下面简单的看一下规范中map的描述,在22.1.3.15章节:
7. Let A be ArraySpeciesCreate(O, len).
方法ArraySpeciesCreate在9.4.2.3,章节:
6. If isArray is true, then
d. If Type(C) is Object, then
i. Let C be Get(C, @@species).
看到这个大概的过程了吧,数组的map,slice,filter,splice,concat方法都是这样的过程。当然还有其它对象的一些API也可能有用到species的时候。
大概知道有这个东西就行了,真正用的地方我感觉不是很多。
最后一个看Symbol.toPrimitive,这个symbol与引用类型和值类型做运算有关系,我们知道运算的时候,引用类型要有一个强制转换的过程,通过这个接口可以控制它。
var arr = [1,2,3,4,5];trace(arr + 10 + "\n"); // 1,2,3,4,510arr[Symbol.toPrimitive] = function(hint) {if (hint == "default" || hint == "number") {// sum all numbersreturn this.reduce( function(acc,curr){return acc + curr;}, 0 );}};trace(arr + 10); // 25
hint值是字符串,有三个:default,number和string。一般来讲+链接运算符传入的是default,乘法等算数运算符传入的是number,String(str)传入的是string,在看个对圆形简单操作的例子:
function Circle(r){this.r = r;}Circle.prototype[Symbol.toPrimitive] = function(hint){if(hint == "default" || hint == "number"){return this.r;}else{return this.r * this.r;}}var c1 = new Circle(5),c2 = new Circle(10);var c3 = new Circle(c1 + c2),c4 = new Circle(c2 - c1),c5 = new Circle(c1 * c2);trace(String(c1) + "\n");//25trace(String(c2) + "\n");//100trace(String(c3) + "\n");//225trace(String(c4) + "\n");//25trace(String(c5) + "\n");//2500
觉得上面的过程是不是有点类似C++或者Swift中的操作符重载?其实这个toPrimitive过程在JS内部一直都有,只不过在ES6中把它暴露出来的,让程序员可以自定义这个过程。JS越来越强大了,但也越来越复杂了。
*以上全部代码在Kinoma Studio中测试通过
- ES6学习——新的语法:Symbols——Symbol.toPrimitive,Symbol.hasInstance,Symbol.toStringTag,Symbol.species
- ES6学习——新的语法:Symbols——Symbol.iterator
- ES6学习——新的语法:Symbol概述
- ES6学习——新的语法:Symbol API介绍
- ES6 — Symbol
- ES6学习——类语法:Symbol.species在实例创建中的应用
- Symbol.hasInstance的理解
- ES6学习——新的语法:Symbol private类属性
- ES6——Symbol数据类型
- 8、Symbol数据类型—ES6学习笔记
- ES6新数据类型 Symbol
- ES6新数据类型Symbol
- symbol
- symbol
- Symbol
- symbol
- Symbol
- Symbol
- POJ-1975 Median Weight Bead(Floyed)
- Android 使用Parcelable传递对象
- 盘点即时战略游戏中高实用性寻路算法
- java151229ExceptionTest
- 2016-01-06 09:42:53.547:WARN:oejs.HttpChannel:qtp2109938810-27: Could not send response error 500: j
- ES6学习——新的语法:Symbols——Symbol.toPrimitive,Symbol.hasInstance,Symbol.toStringTag,Symbol.species
- MFC中Unicode与多字节编码中遇到的CString与char或char*的转化问题
- Spring+Hibernate声明事务
- java自动装箱拆箱总结
- UE4 Hello Slate
- three.js学习笔记 基础1_1
- java151229Demo异常在父子类中的覆盖问题
- [Phonegap+Sencha Touch] 移动开发74 日期时间控件
- nodejs中的underscore.js