如何加入冒险者联盟盟小于等干nan级是什么

澳洲最强“澳洲八校联盟”,看完这篇让你全部了解
澳洲最强的几所五星级的大学,称之为Group of Eight——澳洲八校联盟。中国孩子去过国外留学很多人都选择去澳洲,澳洲有很不错的教育资源,宜人的环境,还有很好的移民政策,众多的澳洲大学中澳洲八大可谓炙手可热,那么南星留学就带大家去了解一下这八所大学:
1 The Australian Nantional University 澳大利亚国立大学
2 The University of Sydney 悉尼大学
3 The University of Melbourne 墨尔本大学
4 The University of New South Wales 南威尔士大学
5 Monash University 莫纳什大学
6 The University of Queensland 昆士兰大学
7 The University of Western Australia 西澳大学
8 Adelaide University 阿德莱德大学
“八大”分布图
1、澳大利亚国立大学
建校时间:始建于1946年,, 1960年增加大学教学,1992年与艺术学院合并。
校址:堪培拉
在校学生:学校现有13000多名在校学生,其中海外留学生有3000多名。
科系:文学,亚洲研究、经贸、工程和信息技术、法律、科学。艺术学院开设了可视艺术、音乐、电动化,艺术课程。八人研究院、若干个研究单位和学术中心开设了生物、化学、物理、医学、地球科学、机械以及信息科学、社会学、太平洋地区和亚洲研究等研究课程。
英语语言服务:ANUTECH教育中心提供从初级到高级课程,包括'雅思'备考课程。
概况:是一所是研究型大学,具有70年校史的澳大利亚国立大学是澳大利亚国家研究中心。在学术界一直处于领导地位。它不断吸引着国内外优秀的教职员工和学生,国立大学的强项是科研和研究生。澳大利亚国立大学的杰出校友包括6名诺贝尔奖得主,居澳大利亚首位;其澳大利亚联邦院士人数超过270名,居澳大利亚首位;其皇家学会的会员人数比澳大利亚的其它所有大学的总和还多。
网址:www.anu.edu.au
2、悉尼大学
建校时间:始建于1850年,是澳大利亚和大洋洲第一所大学。
校址:悉尼大学位于澳大利亚最大的城市-悉尼
科系:学校共有三个学院、19个系,可授予超过490个本科学位与硕士学位。系所包括:农业、食品与自然资源系;建筑系;文学系;澳大利亚管理研究生系;牙科系;经济与商业系;教育与社会工作系;工程系;政府研究生系;健康科学系;法学系;医学系;悉尼艺术系;悉尼音乐系;护理系;药学系;理学系;兽医学系。 悉尼大学的法律系,毋庸置疑,是全澳最有名的。
概况:作为一所综合的,以研究为重点的国际性大学,悉尼大学在全球享有很高知名度。其与广泛的合作伙伴机构开展了众多研究合作、共同办学计划和教学人员与学生交换活动。悉尼大学一直都致力于各种领域课题的研究,已经获得了多项由澳大利亚研究委员会(ARC)和国家健康与医疗研究委员会(NHMRC)提供的竞投项目资金。对于研究方面的大力投入,使学校形成了以研究为主导的教学模式,不仅成果斐然,而且广受赞誉。
杰出校友:悉尼大学在各个领域培养出了众多享誉全球的杰出人物。这些国际名人包括:四位澳大利亚总理(Barton、McMahon、Whitlam和Howard);联合国第一任大会主席 — Herbert Vere Evatt博士;前世界银行行长James Wolfensohn;诺贝尔化学奖得主John Cornforth爵士与Robert Robinson爵士,以及诺贝尔经济学奖得主John Harsanyi荣誉教授;英国皇家学会会长Lord May。
3、墨尔本大学
建校于:1853年
校址:墨尔本大学坐落于澳大利亚文化与工业中心——墨尔本(连续多年被评为“世界最宜居城市”)
科系:建筑、文学、商学、教育、工程、土地和食品资源、法律、医学、音乐、科学和兽医。另外还有维多利亚艺术学院所提供的音乐、舞蹈、美术、戏剧以及电影和电视课程。除此之外,墨尔本商业管理学校和研究所的各科系更提供了学生研究进修的最佳学术去处。
概况:墨尔本大学是一所国际公认的研究大学,与工商界和政府之间有着紧密的联系。墨尔本大学的优越教学传统起于1855年,虽然有着久远的历史,但是,校务与时代的潮流同步,注重新生代的学习方式,并做为成长的目标,此为本大学一贯的治校原则。近几年,墨尔本大学一直为「全国甄选研究补助款」中名列顶尖的大学之一,反映出墨尔本大学长期以来在研究上的出色成 果,墨尔本大学目前与工业界中大约二十个研究中心有合作关系。女性在墨尔本大学研究生研究项目的参与率中持续高达46.4%。 校内的各项设备都是最顶级的。墨尔本大学一向对海外学生照顾有加。校内设有海外学生室,雇有顾问、辅导人员、社工人员、英文和课业助教等来协助学生。本校也和世界各地30个国家的123所学府有姊妹校关系,提供了在校生有机会去接触世界各国的不同教学方式,并提升校内和外界的学术研究关系。
中国学生入学条件:本科:TOEFL570或IELTS6以上; 已在中国大学就读一年,或高中毕业但须先上一年大学预科;授课式硕士:TOEFL575或IELTS6.5,也可以先期在大学或其它语言机构进行语言培训; 已获学士学位或荣誉学士学位或有丰富工作经验;研究式硕士及博士:TOEFL575或IELTS6.5,也可以先期在大学或其它语言机构进行语言培训; 一般要求已获授课式硕士学位。
4、新南威尔士大学
建校时间:创办于1949年
校址:其主校区位于新南威尔士州首府悉尼,旗下另外2所学院—艺术学院和澳大利亚国防学院分别位于悉尼近郊的派丁顿和首都堪培拉。
科系:人文、社会科学系,环境建设系,商科系,工程系,法律系,医学系,科学系,艺术设计学院八个学院,包括艺术、社会科学、生态环境、商业与经济、工程技术、法律、生命科学、医学、科学技术等方面的200个本科、硕士、博士研究生专业课程。
主要设施:8公顷的主校园坐落于肯辛顿,距悉尼的商业区约20分钟路程。艺术学院位于悉尼近郊的帕丁顿,周围有许多艺术博物馆。校内约有100个俱乐部和社会团体,涉及运动、文化、社会、宗教、业余爱好和学术等领域。
概况:新南威尔士大学以其一流的教学和研究水平,多年来连续被“亚洲周刊”评为亚太地区前十位的大学。作为澳洲八大名校之一,同时也是21所涵盖亚洲,欧洲,北美,英国等地名校大学联合会成员之一,1998年有3位获得“罗德斯”奖的学者。对于海外留学申请者,要求雅思6.5,或者通过新南威尔士大学语言学院英语配套课程的成绩优秀生。学生可以申请转学分。学生在学期中可以工作,每周不超过20小时,假期无限制。入学时可向国际中心申请工作许可。
5、莫纳什大学
建校时间:建立于1961年
校址:在墨尔本及周围分部有六个校园,另有校园位于马来西亚吉隆坡及南非约翰内斯堡,共有八个校园。
学生人数:约63000名,其中包括来自100多个国家的约20000名在读留学生。
科系:商业与经济,工程,信息技术,医学,护理和保健,艺术和设计,科学,法律,教育,文科等。以上十个院系均设有本科,硕士及博士生课程。
概况:在澳大利亚莫纳什大学是校园最大,学生最多的综合大学。莫纳什大学具有一流的教学质量及世界领先的科研成果。世界最大的原子能加速器将建在莫纳什大学。莫纳什大学拥有自己的莫纳什学院,为国际留学生进入莫纳什大学提供特殊通路,国际留学生可以通过在莫纳什学院的学习后,直接进入莫纳什大学学习,最终同样获得莫纳什大学学位文凭。莫纳什大学各个校园的学习环境是幽雅的,现代化的,同时又是充满活力,朝气蓬勃的,每年吸引着100多个国家的留学生前来求学,各个校园设有国际留学生办公室,为留学生提供各种服务。每个新学年设有新生周日,所有的新生通过此活动熟悉崭新的留学生活。同时大学拥有100多个学生俱乐部, 可以丰富各类学生的业余生活和满足各类学生的爱好。
大学网址:www.monash.edu.au
6、昆士兰大学
建校:1910年
位置:主校区设址于昆士兰首府布里斯班市内的St.Lucia区,另有Ipswich校区,Gatton校区以及Herston共三个分校区
科系:艺术,生物与化学科学,商业,经济和法律,工程,物理科学和建筑,健康科学,自然资源,农业和植物科学,社会学,行为科学。
师生人数:学生约6,300名,从事教学和研究的教职工2600多人
概况:昆士兰大学是世界一流大学,昆士兰大学在产业资助研究和竞争基金方面是澳大利亚最好的三所大学之一,教学、研究被认为国际一流。作为一个获奖的多媒体图书馆,昆士兰大学的图书馆在昆士兰州是最大的。它在路西亚、加顿和爱普思维奇三个校园及布里斯班教学医院分布着13个分馆。从每一个分馆、或从家里及办公室的计算机上均可得到信息服务。图书馆提供一系列优良的设备和服务,包括目录、数千种电子刊物、250个网络数据库和总数为2百多万种因特网资源。所有的资源通过图书馆的因特风时刻都可以得到。
杰出的毕业生:格拉德·布莱恩那:最高法院的首席法官;彼德·多禾蒂:1996年诺贝尔奖得主,1997年澳大利亚杰出人物;处尔·海顿:前政府官员;乔治佛雷·拉什:奥斯卡奖得主;威那·高期:前昆士兰州的州长。
7、西澳大学
建校时间:西澳大学于1911年建校,是西澳最古老、最有名的大学,也是澳大利亚著名的研究性大学之一。
校址:澳大利亚最大的州—西澳大利亚州的首府柏斯市(Perth)天鹅河畔(SwanRiver),是该州历史最悠久的高等学府。校舍建筑以地中海罗马式风格为主,开阔的园林风景如画,公认为澳洲最美的校园之一。
科系:农学院,工程学和数学学院,文学院,法学院,经济学和商科学院,医学和牙医学学院,教育学院,理学院
入学要求:本科英语成绩要求:雅思6.5分(单项不低于6.0分);硕士英语成绩要求:雅思6.5分(单项不低于6.0分)
概况:澳大利亚西澳大学的一个显著特点就是重视研究及研究培训。该大学是澳大利亚领先的研究型大学之一,也是西澳大利亚州最重要的研究机构。该大学每年可获得115,000,000澳元的外部研究收入,而每年用于研究项目的花费则超过了166,000,000澳元。从建校之初,学校始终把为社会培养优秀专业人才作为首要任务。长期以来,学校对师资水平, 课程设置,教学设施,教学科研工作的计划,实施诸方面进行评估, 已形成了一套扎实的基础。管理严谨的体系,从而保证了教学科研工作的领先水平。另外,校园内的各种俱乐部,社团组织,以及多种文体娱乐设施,为师生丰富多彩的业余生活提供了方便。西澳大学柏斯国际艺术节(UWA Perth International Arts Festival) 是南半球最老的一年一度国际多元文化艺术节,也是西澳最重要的文化活动。
8、阿德莱德大学
建校时间:始建于1874年,是澳大利亚历史上的第三所大学。
校址:位于澳大利亚南部阿德莱德市,阿德莱德大学有四个校区,主校区-North Terrace,Waite校区,Roseworthy校区,Thebarton校区
院系:计算机和数学系,化学工程学院,土木和环境工程学院,澳大利亚Santos石油工程和管理学院,分子生物学学院,科学学院,物理和化学学院,农艺学园艺学,地质学和地球物理学,教育学院,法学院,动物和兽医学院,经济学院,·商学院,建筑,造园术和城市设计系,·阿德莱德工商管理学院,社会科学学院,人文学院,职业学系,·历史与政治学院,音乐学院,人文社会科学系,心理学学院,护理系,临床医学和人口健康学院
概况:阿德雷德大学办学理念的核心是:以学生为首位,学术研究与高质量教学相辅相成,这也是全球所有知名大学的基石和特点。阿德雷德大学致力于培养优秀的毕业生,希望他们在全球范围内得到认可。毕业生除了有蓬勃的创造力,渊博的知识和精湛的技术外,还兼有深厚的文化素养和宽厚的心胸。阿德莱德大学图书馆是南澳大利亚最大的图书馆,它是师生们的主要资料来源。在全球范围内,阿德雷德大学的毕业生组成了十分优秀且广泛的校友会联盟,他们在各国的商业企业、政府机关、学术组织及艺术团体中发挥着重要作用。
入学条件:本科入学:完成国内正规本科大一的学习,成绩满足相应专业的要求或高考达到一本线以上;总分6.5,单项不低于6(托福90,写作不低于24);研究生入学:取得国内相关专业的正规本科学历以及学士学位,成绩满足相应专业的要求;雅思总分6.5,单项不低于6(托福90,写作不低于24);教学硕士要求雅思7.5,口语和听力8分,阅读和写作7分。
澳洲各学校的开学周期:
1. 大学-每年春秋两次,每年的2月和7月;
2. 高中-每年1、4、7、10月共四次;
3. 语言学校每周一开学。
入学要求:
1、学分制,IELTS6.0-6.5,(听说读写必须每门都过6分),大学四年平均
成绩80 以上 方可进入五星大学;
*本文转载自网络,如有侵权,请联系我们处理。
|美国留学|英国留学|澳洲留学|加拿大留学|上海留学资讯|
BeeReady蜂备网官方网站:www.beeready.cn
BeeReady蜂备网官方微博:BeeReady
BeeReady蜂备网头条号:蜂备网留学申请平台
BeeReady蜂备网搜狐平台:蜂备网智能留学平台
责任编辑:
声明:本文由入驻搜狐号的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。
今日搜狐热点从++[[]][+[]]+[+[]]==10?深入浅出弱类型JS的隐式转换 - 简书
从++[[]][+[]]+[+[]]==10?深入浅出弱类型JS的隐式转换
字数 10464
本文纯属原创?
不甚荣幸! 欢迎转载!
原文收录在,觉得本文写的不算烂的,可以点击顺便登录一下账号给个星星?鼓励一下,关注最新更新动态,大家一起多交流学习,欢迎随意转载交流,不要钱,文末没有福利哦?,你懂的?。
如果你很直接,就是直白想看我的结果分析,请直接跳到,只要你看的懂,前面的知识点可以忽略。
凡是都有一个来源和起因,这个题不是我哪篇文章看到的,也不是我瞎几把乱造出来的,我也没这个天赋和能力,是我同事之前丢到群里,叫我们在浏览器输出一下,对结果出乎意料,本着实事求是的精神,探寻事物的本质,不断努力追根溯源,总算弄明白了最后的结果,最后的收获总算把js的隐式类型转换刨根问底的搞清楚了,也更加深入的明白了为什么JS是弱类型语言了。
一看就看出答案的大神可以跳过,鄙文会浪费你宝贵的时间,因为此文会很长,涉及到知识点很多很杂很细,以及对js源码的解读,而且很抽象,如果没有耐心,也可以直接跳过,本文记录本人探索这道问题所有的过程,会很长。
可能写的不太清楚,逻辑不太严密,存在些许错误,还望批评指正,我会及时更正。去年毕业入坑前端一年,并不是什么老鸟,所以我也是以一个学习者的身份来写这篇文章,逆向的记录自己学习探索的过程,并不是指点江山,挥斥方遒,目空一切的大神,如果写的不好,还望见谅。
首先对于这种问题,有人说是闲的蛋疼,整天研究这些无聊的,有啥用,开发谁会这么写,你钻牛角尖搞这些有意思吗?
对于这种质疑,我只能说:爱看不看,反正不是写给你看。
当然,这话也没错,开发过程中确实不会这么写,但是我们要把开发和学习区分开来,很多人开发只为完成事情,不求最好,但求最快,能用就行?。学习也是这样,停留在表面,会用API就行,不会去深层次思考原理,因此很难进一步提升,就是因为这样的态度才诞生了一大批一年经验重复三五年的API大神?。
但是学习就不同,学习本生就是一个慢慢深入,寻根问底,追根溯源的过程,如果对于探寻问题的本质追求都没有,我只能说做做外包就好,探究这种问题对于开发确实没什么卵用,但是对我们了解JavaScript这门语言却有极大的帮助,可以让我们对这门语言的了解更上一个台阶。JavaScript为什么是弱类型语言,主要体现在哪里,弱类型转换的机制又是什么?
有人还是觉得其实这对学习JS也没什么多大卵用,我只能说:我就喜欢折腾,你管得着?反正我收获巨多就够了。
++[[]][+[]]+[+[]]===10?这个对不对,我们先不管,先来看几个稍微简单的例子,当做练习入手。
一、作业例子:
这几个是留给大家的作业,涉及到的知识点下面我会先一一写出来,为什么涉及这些知识点,因为我自己一步步踩坑踩过来的,所以知道涉及哪些坑,大家最后按照知识点一步一步分析,一定可以得出 答案来,列出知识点之后,我们再来一起分析++[[]][+[]]+[+[]]===10?的正确性。
{}+{}//chrome:"[object Object][object Object]",Firfox:NaN
[]+{}//"[object Object]"
首先,关于1、2和3这三个的答案我是有一些疑惑,先给出答案,希望大家看完这篇文章能和我讨论一下自己的想法,求同存异。
13.1+"2"+"2"
14.1+ +"2"+"2"
15.1++"2"+"2"
16.[]==![]
17.[]===![]
这几个例子是我随便写的,几乎包含了所有弱类型转换所遇到的坑,为什么会出现这种情况,就不得不从JS这门语言的特性讲起,大家都知道JS是一门动态的弱类型语言,那么你有没有想过什么叫做弱类型?什么叫做动态?大家都知道这个概念,但有没有进一步思考呢?
今天通过这几个例子就来了解一下JS的弱类型,什么是动态暂时不做探讨。
二、强弱类型的判别
按照计算机语言的类型系统的设计方式,可以分为强类型和弱类型两种。二者之间的区别,就在于计算时是否可以不同类型之间对使用者透明地隐式转换。从使用者的角度来看,如果一个语言可以隐式转换它的所有类型,那么它的变量、表达式等在参与运算时,即使类型不正确,也能通过隐式转换来得到正确地类型,这对使用者而言,就好像所有类型都能进行所有运算一样,所以这样的语言被称作弱类型。与此相对,强类型语言的类型之间不一定有隐式转换。
三、JS为什么是弱类型?
弱类型相对于强类型来说类型检查更不严格,比如说允许变量类型的隐式转换,允许强制类型转换等等。强类型语言一般不允许这么做。具体说明请看。
根据强弱类型的判别定义,和上面的十几个例子已经充分说明JavaScript 是一门弱类型语言了。
先讲一讲一些概念,要想弄懂上面题目答案的原理,首先你要彻底弄懂以下的概念,有些时候对一些东西似懂非懂,其实就是对概念和规则没有弄透,弄透之后等会回过头对照就不难理解,不先了解透这些后面的真的不好理解,花点耐心看看,消化一下,最后串通梳理一下,一层一层的往下剥,答案迎刃而解。
为了能够弄明白这种隐式转换是如何进行的,我们首先需要搞懂如下一些基础知识。如果没有耐心,直接跳到后面第四章我总结的几条结论,这里仅给想要一步步通过过程探寻结果的人看。
四、ECMAScript的运算符、{}解析、自动分号插入
4.1 ECMAScript 运算符优先级
字段访问、数组下标、函数调用以及表达式分组
++ — - + ~ ! delete new typeof void
一元运算符、返回数据类型、对象创建、未定义值
乘法、除法、取模
加法、减法、字符串连接
& &= & &= instanceof
小于、小于等于、大于、大于等于、instanceof
== != === !==
等于、不等于、严格相等、非严格相等
&span class="Apple-tab-span" style="white-space:pre"&&/span&
赋值、运算赋值
4.2 ECMAScript 一元运算符(+、-)
一元运算符只有一个参数,即要操作的对象或值。它们是 ECMAScript 中最简单的运算符。
delete,void,--,++这里我们先不扯,免得越扯越多,防止之前博文的啰嗦,这里咋们只讲重点,有兴趣的可以看看对这几个的详细讲解。
上面的例子我们一个一个看,看一个总结一个规则,基本规则上面例子几乎都包含了,如有遗漏,还望反馈补上。
这里我们只讲 一元加法 和 一元减法 :
我们先看看(熟读规范,你会学到很多很多)对一元加法和一元减法的解读,我们翻到11.4.6和11.4.7。
其中涉及到几个ECMAScript定义的抽象操作,ToNumber(x),ToPrimitive(x)等等 下一章详细解答,下面出现的抽象定义也同理,先不管这个,有基础想深入了解可以提前熟读。
规范本来就是抽象的东西,不太好懂不要紧,我们看看例子,这里的规范我们只当做一种依据来证明这些现象。
大多数人都熟悉一元加法和一元减法,它们在 ECMAScript 中的用法与您高中数学中学到的用法相同。
一元加法本质上对数字无任何影响:
var iNum = 20;
iNum = +iN//注意不要和iNum += iNum搞混淆了;
alert(iNum);
//输出 "20"
尽管一元加法对数字无作用,但对字符串却有有趣的效果,会把字符串转换成数字。
var sNum = "20";
alert(typeof sNum); //输出 "string"
var iNum = +sN
alert(typeof iNum); //输出 "number"
这段代码把字符串 "20" 转换成真正的数字。当一元加法运算符对字符串进行操作时,它计算字符串的方式与 parseInt() 相似,主要的不同是只有对以 "0x" 开头的字符串(表示十六进制数字),一元运算符才能把它转换成十进制的值。因此,用一元加法转换 "010",得到的总是 10,而 "0xB" 将被转换成 11。
另一方面,一元减法就是对数值求负(例如把 20 转换成 -20):
var iNum = 20;
iNum = -iN
alert(iNum);
//输出 "-20"
与一元加法运算符相似,一元减法运算符也会把字符串转换成近似的数字,此外还会对该值求负。例如:
var sNum = "20";
alert(typeof sNum); //输出 "string"
var iNum = -sN
alert(iNum);
//输出 "-20"
alert(typeof iNum); //输出 "number"
在上面的代码中,一元减法运算符将把字符串 "-20" 转换成 -20(一元减法运算符对十六进制和十进制的处理方式与一元加法运算符相似,只是它还会对该值求负)。
4.3 ECMAScript 加法运算符(+)
在多数程序设计语言中,加性运算符(即加号或减号)通常是最简单的数学运算符。
在 ECMAScript 中,加性运算符有大量的特殊行为。
我们还是先看看(熟读规范,你会学到很多很多)对加号运算符 ( + )解读,我们翻到11.6.1。
前面读不懂不要紧,下一章节会为大家解读这些抽象词汇,大家不要慌,但是第七条看的懂吧, 这就是为什么1+"1"="11"而不等于2的原因 ,因为规范就是这样的,浏览器没有思维只会按部就班的执行规则,所以规则是这样定义的,所以最后的结果就是规则规定的结果,知道规则之后,对浏览器一切运行的结果都会豁然开朗,哦,原来是这样的啊。
在处理特殊值时,ECMAScript 中的加法也有一些特殊行为:
某个运算数是 NaN,那么结果为 NaN。
-Infinity 加 -Infinity,结果为 -Infinity。
Infinity 加 -Infinity,结果为 NaN。
+0 加 +0,结果为 +0。
-0 加 +0,结果为 +0。
-0 加 -0,结果为 -0。
不过,如果某个运算数是字符串,那么采用下列规则:
如果两个运算数都是字符串,把第二个字符串连接到第一个上。
如果只有一个运算数是字符串,把另一个运算数转换成字符串,结果是两个字符串连接成的字符串。
var result = 5 + 5; //两个数字
alert(result);
//输出 "10"
var result2 = 5 + "5";
//一个数字和一个字符串
alert(result);
//输出 "55"
这段代码说明了加法运算符的两种模式之间的差别。正常情况下,5+5 等于 10(原始数值),如上述代码中前两行所示。不过,如果把一个运算数改为字符串 "5",那么结果将变为 "55"(原始的字符串值),因为另一个运算数也会被转换为字符串。
注意:为了避免 JavaScript 中的一种常见错误,在使用加法运算符时,一定要仔细检查运算数的数据类型
4.4 ECMAScript 减法运算符(-)
减法运算符(-),也是一个常用的运算符:
var iResult = 2 - 1;
减、乘和除没有加法特殊,都是一个性质,这里我们就单独解读减法运算符(-)
我们还是先看看(熟读规范,你会学到很多很多)对减号运算符 ( - )解读,我们翻到11.6.2。
与加法运算符一样,在处理特殊值时,减法运算符也有一些特殊行为:
某个运算数是 NaN,那么结果为 NaN。
Infinity 减 Infinity,结果为 NaN。
-Infinity 减 -Infinity,结果为 NaN。
Infinity 减 -Infinity,结果为 Infinity。
-Infinity 减 Infinity,结果为 -Infinity。
+0 减 +0,结果为 +0。
-0 减 -0,结果为 -0。
+0 减 -0,结果为 +0。
某个运算符不是数字,那么结果为 NaN。
注释:如果运算数都是数字,那么执行常规的减法运算,并返回结果。
4.5 ECMAScript 前自增运算符(++)
直接从 C(和 Java)借用的两个运算符是前增量运算符和前减量运算符。
所谓前增量运算符,就是数值上加 1,形式是在变量前放两个加号(++):
var iNum = 10;
第二行代码把 iNum 增加到了 11,它实质上等价于:
var iNum = 10;
iNum = iNum + 1;
我们还是先看看(熟读规范,你会学到很多很多)对前自增运算符 ( ++ )解读,我们翻到11.4.4。
此图有坑,后面会说到,坑了我很久。。。
看不懂这些抽象函数和词汇也不要紧,想要深入了解可以通读,看几遍就熟悉了,第一次看见这些肯定一脸懵逼,这是什么玩意,我们只要明白++是干什么就行,这里不必去深究v8引擎怎么实现这个规范的。
console.log(a++);//1
cosole.log(++b);//2
还弄不明白的该好好补习了,这里不在本文的知识点,也不去花篇幅讲解这些,这里我们只要明白一点: 所谓前增量运算符,就是数值上加 1 。
4.6 ECMAScript 自动分号(;)插入
尽管 JavaScript 有 C 的代码风格,但是它不强制要求在代码中使用分号,实际上可以省略它们。
JavaScript 不是一个没有分号的语言,恰恰相反上它需要分号来就解析源代码。 因此 JavaScript 解析器在遇到由于缺少分号导致的解析错误时,会自动在源代码中插入分号。
var foo = function() {
} // 解析错误,分号丢失
自动插入分号,解析器重新解析。
var foo = function() {
}; // 没有错误,解析继续
4.6.2工作原理
下面的代码没有分号,因此解析器需要自己判断需要在哪些地方插入分号。
(function(window, undefined) {
function test(options) {
log('testing!')
(options.list || []).forEach(function(i) {
options.value.test(
'long string to pass here',
'and another long string to pass'
foo: function() {}
window.test = test
})(window)
(function(window) {
window.someLibrary = {}
})(window)
下面是解析器"猜测"的结果。
(function(window, undefined) {
function test(options) {
// 没有插入分号,两行被合并为一行
log('testing!')(options.list || []).forEach(function(i) {
}); // &- 插入分号
options.value.test(
'long string to pass here',
'and another long string to pass'
); // &- 插入分号
// &- 插入分号, 改变了 return 表达式的行为
{ // 作为一个代码段处理
foo: function() {}
}; // &- 插入分号
window.test = // &- 插入分号
// 两行又被合并了
})(window)(function(window) {
window.someLibrary = {}; // &- 插入分号
})(window); //&- 插入分号
解析器显著改变了上面代码的行为,在另外一些情况下也会做出错误的处理。
4.6.3 ECMAScript对自动分号插入的规则
我们翻到7.9章节,看看其中插入分号的机制和原理,清楚只写以后就可以尽量以后少踩坑
必须用分号终止某些 ECMAScript 语句 ( 空语句 , 变量声明语句 , 表达式语句 , do-while 语句 , continue 语句 , break 语句 , return 语句 ,throw 语句 )。这些分号总是明确的显示在源文本里。然而,为了方便起见,某些情况下这些分号可以在源文本里省略。描述这种情况会说:这种情况下给源代码的 token 流自动插入分号。
还是比较抽象,看不太懂是不是,不要紧,我们看看实际例子,总结出几个规律就行,我们先不看抽象的,看着头晕,看看具体的总结说明, 化抽象为具体 。
首先这些规则是基于两点:
以换行为基础;
解析器会尽量将新行并入当前行,当且仅当符合ASI规则时才会将新行视为独立的语句。
4.6.3.1 ASI的规则
1. 新行并入当前行将构成非法语句,自动插入分号。
if(1 & 10) a = 1
console.log(a)
if(1 & 10) a = 1;
console.log(a);
2. 在continue,return,break,throw后自动插入分号
3. ++、--后缀表达式作为新行的开始,在行首自动插入分号
4. 代码块的最后一个语句会自动插入分号
function(){ a = 1 }
function(){ a = 1; }
4.6.3.2 No ASI的规则
1. 新行以 ( 开始
(a+b).toString()
// 会被解析为以a+b为入参调用函数a,然后调用函数返回值的toString函数
var b =a(a+b).toString()
2. 新行以 [ 开始
var a = ['a1', 'a2']
[0,1].slice(1)
// 会被解析先获取a[1],然后调用a[1].slice(1)。
// 由于逗号位于[]内,且不被解析为数组字面量,而被解析为运算符,而逗号运算符会先执
行左侧表达式,然后执行右侧表达式并且以右侧表达式的计算结果作为返回值
var a = ['a1', 'a2']
var b = a[0,1].slice(1)
3. 新行以 / 开始
/test/.test(b)
// /会被解析为整除运算符,而不是正则表达式字面量的起始符号。浏览器中会报test前多了个.号
var b = a / test / .test(b)
4. 新行以 + 、 - 、 % 和 * 开始
// 会解析如下格式
var b = a + a
5. 新行以 , 或 . 开始
.toString()
console.log(typeof b)
// 会解析为
var b = a.toString()
console.log(typeof b)
到这里我们已经对ASI的规则有一定的了解了,另外还有一样有趣的事情,就是“空语句”。
// 三个空语句
// 只有if条件语句,语句块为空语句。
// 可实现unless条件语句的效果
if(1&2);else
console.log('2 is greater than 1 always!');
// 只有while条件语句,循环体为空语句。
while(++a & 100);
4.6.4 结论
建议绝对不要省略分号,同时也提倡将花括号和相应的表达式放在一行, 对于只有一行代码的 if 或者 else 表达式,也不应该省略花括号。 这些良好的编程习惯不仅可以提到代码的一致性,而且可以防止解析器改变代码行为的错误处理。
我们可以看看知乎上大牛们对着个问题的看法。
4.7 ECMAScript 对{}的解读,确切说应该是浏览器对{}的解析
js引擎是如何判断{}是代码块还是对象的?
这个问题不知道大家有没有想过,先看看几个例子吧?
首先要深入明白的概念:
4.7.1 JavaScript的语句与原始表达式
原始表达式是表达式的最小单位——它不再包含其他表达式。javascript中的原始表达式包括this关键字、标识符引用、字面量引用、数组初始化、对象初始化和分组表达式,复杂表达式暂不做讨论。
语句没有返回值,而表达式都有返回值的,表达式没有设置返回值的话默认返回都是undefined。
在 javascript 里面满足这个条件的就函数声明、变量声明(var a=10是声明和赋值)、for语句、if语句、while语句、switch语句、return、try catch。
但是 javascript 还有一种函数表达式,它的形式跟函数声明一模一样。如果写 function fn() { return 0;} 是函数声明而写var a = function fn(){ return 0;} 等号后面的就是函数表达式。
4.7.2 再来看看几个例子吧
我们直接在chrome看看结果:
很奇怪是吧:
再来看看在Firefox下面的情况:
其他IE没测,我Mac没法装IE,大家自行测试。
第二个很好理解,在有;的情况下,chrome和Firefox一致的把{a:1}解析为代码块,那么{a:1}怎么理解这个代码块,为什么不报错,还记得goto语句吗,JavaScript保留了goto的语法,我最先也半天没缓过神来,还好记得c语言里面的这个语法,没白学,其实可以这么理解:
关于第二个{a:1}+1的答案,chrome和Firefox接过也一致,两个浏览器都会把这段代码解析成:
其中关于{a:1}两个浏览器就达成了不一样的意见,只要{}前面没有任何运算符号,Firefox始终如一的把{}解析成{};也就是我们熟知的代码块,而不是对象字面量。
而chrome就不同了,如果{a:1}后面和前面啥也没有,{a:1}在chrome浏览器会首先检查这个是不是标准对象格式,如果是返回这个对象,如果不是,则当做代码块执行代码。当然这种情况基本可以不考虑,你写代码就写个{a:1}然后就完了?
共同的特点:
当{}的前面有运算符号的时候,+,-,*,/,()等等,{}都会被解析成对象字面量,这无可争议。
当{}前面没有运算符时候但有;结尾的时候,或者浏览器的自动分号插入机制给{}后面插入分号(;)时候,此时{}都会被解析成代码块。
如果{}前面什么运算符都没有,{}后面也没有分号(;)结尾,Firefox会始终如一的解析为代码块,而chrome有细微的差别,chrome会解析为对象字面量。
这里也是我通过浏览器输出结果进行的一种归纳,当然可能还有没有总结到位的地方,也可能还有错误,发现对于{}何时解析为对象何时解析为代码块也没有找到比较详细的解答,有可能也是我看的不仔细,遗漏了这块,还望大家能解答一下这块。
如果你觉得以上的很繁琐,我是新手,也看不太懂,不要紧,不要慌,循序渐进,以后会懂的,这里我就直接总结出几个结论,总结的不对的地方,还望反馈指出,对照着结论来验证上面的十几个例子:
数组下标([])优先级最高, 一元运算符(--,++,+,-)的优先级高于加法或减法运算符(+,-);
++前增量运算符,就是数值上加 1;
一元运算符(+,-)的后面如果不是数字,会调用 ToNumber 方法按照规则转化成数字类型。
对于加号运算符(+)
首先执行代码,调用 ToPrimitive 方法得到原始值
①如果原始值是两个数字,则直接相加得出结果。
②如果两个原始值都是字符串,把第二个字符串连接到第一个上,也就是相当于调用 concat 方法。
③如果只有一个原始值是字符串,调用 ToString 方法把另一个运算数转换成字符串,结果是两个字符串连接成的字符串。
对于减号运算符(-)
不知道大家有没有看到规范,这里比+少了一步 ToPrimitive
,所以 - 相对容易理解。
①如果是两个数字,则直接相减得出结果。
②如果有一个不是数字,会调用 ToNumber 方法按照规则转化成数字类型,然后进行相减。
分号的插入
①新行并入当前行将构成非法语句,自动插入分号。
②在continue,return,break,throw后自动插入分号
③++、--后缀表达式作为新行的开始,在行首自动插入分号
④代码块的最后一个语句会自动插入分号
⑤新行以 ( 、[、\、+ 、 - 、,、. % 和 *开始都不会插入分号
{}的两种解读
①当{}的前面有运算符号的时候,+,-,*,/,()等等,{}都会被解析成对象字面量,这无可争议。
②当{}前面没有运算符时候但有;结尾的时候,或者浏览器的自动分号插入机制给{}后面插入分号(;)时候,此时{}都会被解析成代码块。
③如果{}前面什么运算符都没有,{}后面也没有分号(;)结尾,Firefox会始终如一的解析为代码块,而chrome有细微的差别,chrome会解析为对象字面量。
五、ECMAScript的规范定义的抽象操作
前面关于的解读,涉及到几个重要的抽象操作:
GetValue(v) : 引用规范类型
Type(x) : 获取x的类型
ToNumber(x) : 将x转换为Number类型
ToString(x) : 将x转换为String类型
SameValue(x,y) : 计算非数字类型x,y是否相同
ToPrimitive(x) : 将x转换为原始值
5.1 原始值
首先,让我们快速的复习一下。 在 JavaScript 中,一共有两种类型的值(ES6的 symbol 暂不做讨论):
原始值(primitives)
1. undefined
3. boolean
对象值(objects)。
除了原始值外,其他的所有值都是对象类型的值,包括数组(array)和函数(function)等。
5.2 GetValue(v)
这里的每个操作都有其严格并复杂的定义,可以直接查阅ECMA规范文档对其的详细说明。
附上在线中文文档地址:
我们先看看GetValue(v) : 引用规范类型,下面是的解读:
这什么鬼,我也不太懂,反正就是关于引用规范的一些抽象描述,鄙人才疏学浅,也不能化抽象为具体的解释一番,太抽象了,好难啊,功力还不够,不懂但对我们解决上面的问题也没有什么影响,我们只看关键的几个:
这里我们先看下SameValue()和ToPrimitive()两个操作。
5.3 SameValue(x,y)
我们还是先看看(熟读规范,你会学到很多很多)对 SameValue 方法解读,我们翻到9.12。
这个SameValue操作说的就是,如果x,y两个值类型相同,但又不同时是Number类型时的比较是否相等的操作。
5.4 ToPrimitive(input [ , PreferredType])
ToPrimitive() 方法
转换成原始类型方法。
还是来看看 ECMAScript 标准怎么定义 ToPrimitice 方法的:
是不是看了这个定义,还是一脸懵逼,ToPrimitive这尼玛什么玩意啊?这不是等于没说吗?
再来看看火狐MDN上面文档的介绍:
查了一下资料,上面要说的可以概括成:
ToPrimitive(obj,preferredType)
JS引擎内部转换为原始值ToPrimitive(obj,preferredType)函数接受两个参数,第一个obj为被转换的对象,第二个
preferredType为希望转换成的类型(默认为空,接受的值为Number或String)
在执行ToPrimitive(obj,preferredType)时如果第二个参数为空并且obj为Date的事例时,此时preferredType会
被设置为String,其他情况下preferredType都会被设置为Number如果preferredType为Number,ToPrimitive执
1. 如果obj为原始值,直接返回;
2. 否则调用 obj.valueOf(),如果执行结果是原始值,返回之;
3. 否则调用 obj.toString(),如果执行结果是原始值,返回之;
4. 否则抛异常。
如果preferredType为String,将上面的第2步和第3步调换,即:
1. 如果obj为原始值,直接返回;
2. 否则调用 obj.toString(),如果执行结果是原始值,返回之;
3. 否则调用 obj.valueOf(),如果执行结果是原始值,返回之;
4. 否则抛异常。
首先我们要明白 obj.valueOf() 和 obj.toString() 还有原始值分别是什么意思,这是弄懂上面描述的前提之一:
toString用来返回对象的字符串表示。
var obj = {};
console.log(obj.toString());//[object Object]
var arr2 = [];
console.log(arr2.toString());//""空字符串
var date = new Date();
console.log(date.toString());//Sun Feb 28 :36 GMT+0800 (中国标准时间)
valueOf方法返回对象的原始值,可能是字符串、数值或bool值等,看具体的对象。
var obj = {
name: "obj"
console.log(obj.valueOf());//Object {name: "obj"}
var arr1 = [1];
console.log(arr1.valueOf());//[1]
var date = new Date();
console.log(date.valueOf());//3
如代码所示,三个不同的对象实例调用valueOf返回不同的数据
原始值指的是['Null','Undefined','String','Boolean','Number']五种基本数据类型之一,一开始就提到过。
弄清楚这些以后,举个简单的例子:
ToPrimitive(a)
分析:a是对象类型但不是Date实例对象,所以preferredType默认是Number,先调用a.valueOf()不是原始值,继续来调
用a.toString()得到string字符串,此时为原始值,返回之.所以最后ToPrimitive(a)得到就是"[object Object]".
如果觉得描述还不好明白,一大堆描述晦涩又难懂,我们用代码说话:
const toPrimitive = (obj, preferredType='Number') =& {
let Utils = {
typeOf: function(obj) {
return Object.prototype.toString.call(obj).slice(8, -1);
isPrimitive: function(obj) {
let types = ['Null', 'String', 'Boolean', 'Undefined', 'Number'];
return types.indexOf(this.typeOf(obj)) !== -1;
if (Utils.isPrimitive(obj)) {
preferredType = (preferredType === 'String' || Utils.typeOf(obj) === 'Date') ?
'String' : 'Number';
if (preferredType === 'Number') {
if (Utils.isPrimitive(obj.valueOf())) {
return obj.valueOf()
if (Utils.isPrimitive(obj.toString())) {
return obj.toString()
if (Utils.isPrimitive(obj.toString())) {
return obj.toString()
if (Utils.isPrimitive(obj.valueOf())) {
return obj.valueOf()
ToPrimitive(a);//"[object Object]",与上面文字分析的一致
5.5 ToNumber(x)
这个就比ToPrimitive() 方法好理解多了,就是把其他类型按照一定的规则转化成数字类型,也就是类似Number()和parseInt()的方法。
还是继续看看ECMAScipt规范中对于Number的转换
是不是又看到 ToPrimitive() 方法了,是不是看了上面的就好理解多了,如果ToNumber(x)这个x是对象就要调用ToPrimitive方法返回x的原始值,是不是一下子就串起来了。
5.6 ToString(x)
这个理解起来跟 ToNumber 方法大同小异,还是继续看看ECMAScipt规范中对于String的转换.
对数值类型应用 ToString
ToString 运算符将数字 m 转换为字符串格式的给出如下所示:
如果 m 是 NaN,返回字符串 "NaN"。
如果 m 是 +0 或 -0,返回字符串 "0"。
如果 m 小于零,返回连接 "-" 和 ToString (-m) 的字符串。
如果 m 无限大,返回字符串 "Infinity"。
否则,令 n, k, 和 s 是整数,使得 k ≥ 1, 10k-1 ≤ s & 10k,s × 10n-k 的数字值是 m,且 k 足够小。要注意的是,k 是 s 在十进制表示中的数字的个数。s 不被 10 整除,且s 的至少要求的有效数字位数不一定要被这些标准唯一确定。
如果 k ≤ n ≤ 21,返回由 k 个 s 在十进制表示中的数字组成的字符串(有序的,开头没有零),后面跟随字符 '0' 的 n-k 次出现。
如果 0 & n ≤ 21,返回由 s 在十进制表示中的、最多 n 个有效数字组成的字符串,后面跟随一个小数点 '. ',再后面是余下的 k-n 个 s 在十进制表示中的数字。
如果 -6 & n ≤ 0,返回由字符 '0' 组成的字符串,后面跟随一个小数点 '. ',再后面是字符 '0' 的 -n 次出现,再往后是 k 个 s 在十进制表示中的数字。
否则,如果 k = 1,返回由单个数字 s 组成的字符串,后面跟随小写字母 'e',根据 n-1 是正或负,再后面是一个加号 '+' 或减号 '-' ,再往后是整数 abs(n-1) 的十进制表示(没有前置的零)。
返回由 s 在十进制表示中的、最多的有效数字组成的字符串,后面跟随一个小数点 '. ',再后面是余下的是 k-1 个 s 在十进制表示中的数字,再往后是小写字母 'e',根据n-1 是正或负,再后面是一个加号 '+ ' 或减号 '-' ,再往后是整数 abs(n-1) 的十进制表示(没有前置的零)。
六、验证分析++[[]][+[]]+[+[]]==10?
养兵千日,用兵一时。
了解了这么多深入的基础知识,该发挥用武之地了,我已经用完洪荒之力了,是时候表演真正的技术了。
好像前面忘记讲 == 符号了,不要紧,之前这个我的上一篇博文已经非常详细的分析过了,可以看看我的这篇。这里就不花篇幅介绍了,感觉越来越坑,越写越多。
这里就简单说一下,总结一下==转换规则:
==运算规则的图形化表示
1. undefined == null,结果是true。且它俩与所有其他值比较的结果都是false。
2. String == Boolean,需要两个操作数同时转为Number。
3. String/Boolean == Number,需要String/Boolean转为Number。
4. Object == Primitive,需要Object转为Primitive(具体通过valueOf和toString方法)。
瞧见没有,一共只有4条规则!是不是很清晰、很简单。
1.首先++[[]][+[]]+[+[]]首先拆分一下:
根据 4.1 ECMAScript 运算符优先级 可以这样拆分:
相当于这样:
(++[[]][+[]])
2.先来分析右边的[+[]]
①先看里面的+[]
根据 4.2 ECMAScript 一元运算符(+、-) 可以知道,一元运算符会调用 ToNumber 方法把 ToNumber([]) 转化成数字。
根据 5.5 ToNumber(x) 的转换规则,x为[]是数组对象,因此会调用 ToPrimitive 方法。
根据 5.4 ToPrimitive(input [ , PreferredType]) 的转换规则,空数组先调用 valueOf() 方法,得到[]不是原始值,继续调用 toString() 方法,得到 ""空字符串 。
递归的调用之后成了 ToNumber("") ,答案显而易见,根据 5.5 ToNumber(x) 的转换规则对照图片可以看出ToNumber("")===0。 那么[+[]]就变相的成了[0] 。
此时成了(++[[]][+[]])+[0]
3.再来分析左边边的++[[]][+[]]
+[]上面已经分析出来了,结果为0,那么此时就成了++[[]][0]
根据 4.2 ECMAScript 一元运算符(+、-) 可以知道,数组下标的优先级高于一元运算符++,那么理所当然成了这样 ++([[]][0]) ,而[[]][0]可以看出数组下标为0也就是第一个元素,此时为[],那么最后成了++[].
++[]这是什么鬼?,根据 4.5 ECMAScript 前自增运算符(++) 没有发现任何有调用 ToNumber 的方法,浏览器试了一下,果然有问题,报错啦,到底哪里出问题了呢,为什么走着走着就走偏了。问题出在哪一步呢?
4.分析问题错误的原因
为什么++([[]][0])在浏览器不报错,而++[]报错,我知道问题就出在这一步,但是一直相不出原因,光瞎想是没用的,没事继续读读ECMAScript规范,然后中文版的并没有看出什么玩意,最后在github英文版找到原因了。
首先我们在浏览器输出一下++[]
无意之中照着错误搜,搜到了这个后缀自增++:
顺便看看大同小异的前缀自增++
Increment Operator_操作的第5步PutValue(expr, newValue)要求expr是引用。这就是问题的关键,为什么之前我没发现,因为之前我一直看的是中文版,来看看中文版的截图对比一下
发现后面的3,4,5都没有,我一度以为自己理解错了,为什么这个规则没有调ToNumber()却也能得到数字,原来是翻译中这块内容遗漏了,我该好好补习英语了,尽量多看英文文档。
看到第五条大大的 Call PutValue(expr, newValue). ,
阅读,可以看到Prefix Increment Operator操作的第5步PutValue(expr, newValue)要求expr是引用。
我们还是来看看 PutValue 到底是什么定义,这里我们只需要知道++a,这个a是引用类型才不会报Uncaught ReferenceError: Invalid left-hand side expression in postfix operation这个错误。
而我们知道[[]][0]是对象的属性访问,而我们知道对象的属性访问返回的是引用,所以可以正确执行。
5.进一步拆分
++[[]][0]可以这么拆分,只要保持引用关系就行:
var refence=[[]][0];
再来进一步拆分
var refence=[];
refence=refence+1;
最后就成了
refence=[]+1;
根据 4.3 ECMAScript 加法运算符(+) ,[]+1可以看成是ToPrimitive([])+ToPrimitive(1),根据 5.4 ToPrimitive(input [ , PreferredType]) 的转换规则,空数组先调用 valueOf() 方法,得到[]不是原始值,继续调用 toString() 方法,得到 "" 空字符串。
于是就成了 ""+1 ,根据 4.3 ECMAScript 加法运算符(+) ,有一个字符串,另外一个也会变成字符串,所以""+1==="1"。所以 ++[[]][0] === "1" ;
好像分析的是这么回事,其实错了,大家不要跟着我错误的步骤走,我其实忽略了很重要的一点。
看看规范有一点遗漏了,就是 Let oldValue be ToNumber(GetValue(expr)).
就是++时候旧的值要进行 ToNumber() 运算,最后最后一步应该是这样子的:
refence=ToNumber([])+1;
ToNumber([])===0,别问我为什么,照着我上面的分析自己分析一遍,不难,我因为分析多了,所以一眼就看出来了,所以最后成了0+1=1的问题,所以 ++[[]][0] === 1 。
6. 谜底揭开?
左边++[[]][0] === 1;
右边[+[]]的值为[0];
所以最后成了1+[0]的问题了。
根据 5.4 ToPrimitive(input [ , PreferredType]) 的转换规则,[0]数组先调用 valueOf() 方法,得到[0]不是原始值,继续调用 toString() 方法,得到 “0” 的字符串。
所以最后就成了 1+"0"==="10" 。
7.最后的最后
于是最后就成了 "10" == 10 的问题,根据ECMAScript规范==的对应法则:
对比第5条,可以发现最后成了ToNumber("10")与10的比较,而ToNumber("10") === 10,
左边最后 === 10,
右边最后 === 10。
10 === 10为true.
所以 ++[[]][+[]]+[+[]]==10 为true,大功告成,可喜可贺,实力分析了一波,有错误还望批评指正。
七、我的疑惑
1. {}+{}//chrome:"[object Object][object Object]",Firfox:NaN
2. {}+[]//0
3. []+{}//"[object Object]"
通过这个例子,我发现刚才4.7 ECMAScript 对{}的解读还不够彻底,首先我们按照前面常规的思维来解答:
1.第一种思维:第一个{}解析为对面字面量
第一例子: {}+{} 首先左边{}和右边{}会调用 ToPrimitive 两边都会得到:"[object Object]",所以最后就是这两个相同的字符串相加,得到: "[object Object][object Object]" ,chrome符合,Firefox不符合。
第二个例子: {}+[] 按照这种思维首先左边{}和右边[]会调用 ToPrimitive ,分别得到"[object Object]"和""空字符串,那么相加结果应该是 "[object Object]" ,为什么结果成了 0 ,而且在 chrome 和 Firfox 都是0?
第三个例子: []+{} 按照这种思维首先左边[]和右边{}会调用 ToPrimitive ,分别得到""空字符串和"[object Object]",最后相加结果 "[object Object]" ,这个没有任何疑惑,chrome和Firefox都符合。
2.第一种思维:第一个{}解析为代码块
第一例子: {}+{} 浏览器这么解析,把{}不解析为对象字面量而是代码块,也就是let a={}这种块,代码可以看成是这样 {};+{} ,那么{};执行啥也没有,接下来就是 +{} ,+是一元运算符,上面讲到了,这里+{}执行时候首先会调用ToNumber(),参数{}是object会首先调用 ToPrimitive 得到原始值: "[object Object]" ,这时候就可以发现ToNumber("[object Object]")转化的就是 NaN 了,chrome不符合,Firefox符合。
第二个例子: {}+[] 按照这种思维,最后解析成 {};+[] ,+是一元运算符,上面讲到了,这里+[]执行时候首先会调用ToNumber(),参数[]是object会首先调用 ToPrimitive 得到原始值: ""空字符串 ,最后根据规则ToNumber("")得到数字0.这种思维下没有任何疑惑,chrome和Firefox都符合。
第三个例子: []+{} 首先左边[]和右边{}会调用 ToPrimitive ,分别得到""空字符串和"[object Object]",最后相加结果 "[object Object]" ,这个没有任何疑惑,chrome和Firefox都符合。
那么问题来了?问题的矛盾就在于第一条和第二条,chrome和Firefox对于{}+{}解析是不一样的,对于第一个{}chrome解析为对象字面量,而Firefox解析为代码块,这无可厚非, 关键是第二个例子{}+[] ,既然第一个例子 {}+{} 的第一个{}chrome解析为对象字面量而第二个例子 {}+[] 中,chrome却解析为代码块,匪夷所思,有谁能扒一扒源码分析一下,chrome对{}的详细解析,到底什么时候解析为代码块,什么时候解析为对象字面量?有点想不明白为什么这么不一致,而 Firefox始终如一,第一个{}一直解析为代码块,运算符号后面{}解析为对象字面量。
3.捉摸不透
Firefox的我能理解,开头{}一律解析为代码块(block),而chrome却让人捉摸不透。。。
前面的十几个例子,大家有兴趣对照着规则自己一个一个做做,看看自己是否真的理解了,理解了也再熟悉一遍,学习本来就是一个重复的过程。
突然灵机一动:
var obj = {
valueOf: function() {
return 18;
console.log(
"1" &= "a",
obj &= "17"
这个答案又是多少呢?
var obj = {
valueOf: function() {
return {a:1};
toString:function(){
console.log(obj==[]);
最后这个呢?
var obj = {
valueOf: function() {
return {a:1};
toString:function(){
return "0";
console.log(obj==[]);
九、相关资料
(厚颜无耻的也参考一下自己文章)
十、我的GitHub博客
博客签名:若批评无自由,则赞美无意义。
博客宗旨:从现象看本质,再从本质回归到现象。
博客目的:给自己一个回头看看自己精神世界的时光机。
博客主人:Too young,too simple.Sometimes,naive & stupid.
博客座右铭:生活不止眼前的苟且,还有看不到的bug和读不懂的code。
行远自迩,登高自卑,与君共勉。
风光三月连樱笋,美人踌躇白日静。
March 5, 2017 >> (原)
March 1, 2017 >> (原)
不知细叶谁裁出,二月春风似剪刀。
February 26, 2017 >> (原)
February 24, 2017 >> (原)
February 22, 2017 >> (原)
码梦为生,笔耕不辍。
第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一行一行地执行。一般情况下,每一行就是一个语句。 语句(statement)是为了完成某种任务而进行的操作,比如下面就是一行赋值语句: 这条语句先用var命令,声...
第3章 标准库 Object对象 概述 JavaScript原生提供一个Object对象(注意起首的O是大写),所有其他对象都继承自这个对象。Object本身也是一个构造函数,可以直接通过它来生成新对象。 Object作为构造函数使用时,可以接受一个参数。如果该参数是一个对...
第三章 3.1语法3.1.1区分大小写3.1.2标识符所谓标识符,就是指变量,函数,属性的名字,或者函数的参数。规则:第一个字符必须是一个字母,下划线,或一个美元符号其他字符可以是字母,下划线美元符号或数字 注意,不能将关键字,保留字,true,false和null用作标识...
第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型和基本包装类型 用类型的值(对象)是引用类型的-个实例。在ECMAScript中,引用类型是--种数据结构, 1 I用于将数据和功能组织在一起。它也常被称为类,...
标签: 我的笔记 ---学习资料:http://javascript.ruanyifeng.com/ 1. 导论 JavaScript的发明目的,就是作为浏览器的内置脚本语言,为网页开发者提供操控浏览器的能力。 近年来,JavaScript的使用范围,慢慢超越了浏览器,正在...
拉开窗帘, 又是海霞满天。 潮平浪稳, 涛声依旧, 风暴过去了, 上帝还在。 没有荔枝的激流岛, 有葡萄美酒。 常有明月, 又何愁不见归帆。
写于复活节星期一
其实我很满足了不是吗 我至少知道了你的名字你的电话 听过你的声音看过你的眼睛 至少你知道我喜欢你 至少你知道不管你怎样我都喜欢你 尽管我很难过 你不喜欢我我还是会喜欢你.
所谓爆点,往往用来形容新兴业态爆炸性突破的那一刻。 2014年后,交通领域的共享单车、光伏电站运维金融领域的智能投顾、汽车领域的自动驾驶都出现过人们口中的爆点。不难发现,这些爆点都离不开一个重要条件——互联网平台。 传统企业的一大痛点,在于聚合资源能力有限,而互联网平台恰好...
3月5日,李克强总理在政府工作报告中提出:今年网络提速降费要迈出更大步伐,年内全部取消手机国内长途和漫游费。 总理话音刚落,三大运营商立即做出回应。在国新办今天举行的国务院政策例行吹风会上,三大运营商表示,今年10月1日起将全面实施取消手机国内长途和漫游费。 全国人民皆大欢...
一九四0年的暑假里,一个星期日下午,三姐也在爸爸这边。爸爸和我们姐妹都在我们卧室里说着话。忽然来了一位怪客。她的打扮就和《围城》里的鲍小姐一个模样。她比《围城》电视剧里的鲍小姐个儿高,上身穿个胸罩,外加一个透明的蜜黄色蕾丝纱小坎肩,一条紧身三角裤,下面两条健硕肥白的长腿,脚...}

我要回帖

更多关于 冒险者的试炼 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信