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中测试通过


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 帝豪gs加了乙醇汽油怎么办 命理五行缺木怎么办 微信改名含有特殊符号怎么办 户口名字打错了怎么办 寻仙会心几率差怎么办 注册商标下来了没收到怎么办 金融公司倒闭欠的钱怎么办 买车贷款被骗了怎么办 定投终止后钱怎么办 受到小贷公司催款威胁怎么办 合同保证金单据丢了怎么办 公司注销期间发现欠税怎么办 公司注销后银行账户怎么办 注销公司营业执照和公章丢失怎么办 工商核名过期了怎么办 核名后的许可没办下来怎么办 重庆公司核名有同名的怎么办 新电视不全屏怎么办左右有黑边 所学类别找不到音乐表演怎么办 公司口头通知不续签合同怎么办 雪纺衬衣皱了怎么办 狗打架受伤怎么办泰迪 大狗打架破了怎么办 舌头上长溃疡怎么办吃什么药 悠悠球不回弹怎么办啊 围棋遇到对方不停围堵怎么办? s围棋业余四段想提升怎么办 wps禁止创建分享链接怎么办 驾驶人开车违章不认可怎么办 京东白条退货分期服务费怎么办 新车年检标丢了怎么办 异地违章罚单丢了怎么办 异地现场违章罚单丢了怎么办 新车没有牌照过停车杆怎么办 驾照换证时间过了怎么办 杭州告知单丢了怎么办 电工证过了复审日期怎么办 大人有居住证小孩没有怎么办 异地补办身份证没有暂住证怎么办 挂科了心里难受怎么办 c1升b2考不过怎么办