简介JavaScript是每个程序员都绕不开的编程语言。靠着浏览器的支持,牢牢占据着前端编程市场,加上nodejs,在服务端编程中也占有一席之地。很多程序员对它又爱又恨,喜欢它的灵活方便,讨厌它过于灵活的类型转换、复杂的包管理等等。今天,我想从一个非JavaScript程序员的角度,谈谈我对JavaScript的了解,作为我多年来反复品味的总结。网页第一次接触到JavaScript是十多年前的QQ空间。当时的QQ空间是一个精致的网页,可以由用户自行设置。好看的衣服只能用Q币购买,或者黄钻充值。而很多人既不想充值,又想让自己的空间变得不那么普通,于是就有人发现直接在地址栏输入神秘代码就可以得到服装。当时网上搜索频率最高的是“QQ空间装扮密码”。具体原理我还没搞清楚。是开发商故意留下的免费衣服,还是有人找了后门。不管怎样,正如我后来了解到的那样,其中一些代码是JavaScript。时光倒流,回到互联网刚刚出现的时代,最早的网络只有HTML。毕竟有网速和显示设备的限制,能看到纯文本的网页已经让人惊奇了。后来,人们对美好生活的追求逐渐提高,相应地,网页也有了更加丰富多彩的效果。于是就有了CSS样式,后来,人们想在浏览器中运行代码,也就是直接在用户设备上运行普通代码。所以就有了各种替代方案,比如Java等等。最终,Netscape推出的JavaScript获得了最广泛的采用。这个名字据说是为了赶上当年Java的流行。为了让普通人尽快上手,获得最多的用户,JavaScript也做了一些特殊的适配。例如,在语法方面,字符串可以使用单引号或双引号;表达式可以以分号结束,也可以不加分号。这可以防止程序员因为语法好恶而放弃这门语言。在函数方面,它提供了方便的类型转换,数字、数组、函数可以通过+直接转换成字符串:leta=1;a+="2"//'12'letb=[1,2,3];b+="2"//'1,2,32'让c=()=>{};c+="2"//'()=>{}2'可能是因为Web页面需要展示给用户,数据转成字符串,是经常用到的操作。OO忘了是什么时候了,可能是刚接触编程的时候,经常听人说:“JavaScript中的一切都是对象”,那时候还不明白什么是对象。现在我愿意把它理解成一个类似于哈希表的结构,里面有一些预制的项。例如.constructor.name表示这个对象是由哪个类创建的,默认是“Object”类。Numbers属于“Number”类,false属于“Boolean”类。但是现在我至少可以举出两个例子来反驳上面的断言,undefined和null都不是对象。ObjectOriented(面向对象)编程概念是由AlanKay提出的,它似乎首先被用在了SmallTalk语言中。重点是在编程时模拟现实世界的物体,比如汽车、苹果、动物等,都可以看成是一个对象,对象之间通过消息传递进行通信。我不敢说在JavaScript中实际使用了多少面向对象的原则。个人觉得,除了用Object这个名字,其他的好像和面向对象的初衷关系不大。当然,面向对象和编程中的其他一些概念是一样的。已经严重背离了初衷。JavaScript中有两种赋值方式,一种是值传递,一种是引用传递。数字、布尔值、undefined、null等基本数据结构都是按值传递的,即赋值给一个新的变量时,会创建一个新的数据,与原来的数据无关:leta=9;让b=a;a+=1;//10b//9而那些比较复杂的对象是通过引用传递的,也就是把数据的地址传给新的变量,相当于变量只是一个访问数据的入口,而不是数据本身:让a={x:1};让b=a;a.x+=1;b.x//2这种大量使用引用似乎已经成为面向对象的标志性特征。有了这种机制,程序员可以很方便地操作多个关系错综复杂的对象,这在网络编程中很常见。因此,也可以说JavaScript就是为了适应web编程而设计的。比如一个页面上可能有十几个按钮,十几个输入框,各种文本框,它们之间可能有复杂的交互。这个时候这个隐式指针操作起来就很方便了:leta={x:1}letb={child:a}b.child.x+=1;a.x//2个函数有什么特别的?哪种语言没有函数?JavaScript函数也不例外。我们知道其他一些语言也有Modules,函数必须定义在某个模块中。JavaScript其实也类似,函数必须属于某个对象。有人说不对,我就写一个:functionf(){}thisdoesn'tbelongtoanyobject?不是,因为JavaScript本身有一个全局对象,在浏览器中就是window。不知道在nodejs里是什么,但是肯定有一个全局对象。在函数中,使用this访问它所在的对象:leta={name:"a",f:function(){returnthis.name}}a.f()//'a'但请注意,JavaScript函数分为函数函数和箭头函数两种。箭头函数无论在哪里调用,里面的this都是定义时作用域的this:leta={name:"a",f:function(){return()=>this.name}}a.在JavaScript中,只有Function可以创建自己的作用域:leta={x:x=1}x//1普通对象不能创建作用域,所以我们可以从外部访问xletf=()=>{y=1}y//y未定义函数可以创建自己的域,不能从外部访问的类也是一个Function。这是其他语言中比较常见的设计,将数据类型分为两类:函数和值。对象属于值的范畴。闭包JavaScript的可变属性也引出了一种神奇的函数玩法,也是面试官的最爱——闭包。说实话,我觉得这东西普通人用起来不太好,但是不妨碍高手玩好。简单来说,我们可以创建一个函数并创建一个只有该函数可以访问的变量:letadd=(()=>{letx=0;return()=>x+=1;})();add()//1add()//2这还是基于Function的作用域规则:定义在函数体中的变量,在函数体之外是无法访问的。那有什么好处?即在其他语言中,也有类似“private”的关键字,可以定义对象的私有项(字段),但JavaScript没有这种东西,对象的所有项都是公有的。闭包也使得在JavaScript中拥有私有项成为可能。eventloop最后说一下我理解的eventloop。因为JavaScript一般运行在单进程中,这个进程有一个消息队列,运行时会不定期的检查消息队列中的消息,或者事件(Event),并按照先进先出的顺序处理这些事件:setTimeout(()=>console.log('1'))//塞进邮箱setTimeout(()=>console.log('2'))//塞进邮箱console.log('0')//print//终于有时间可以查邮箱了//0//1//2个人感觉JavaScript将单进程的能力开发到了极致,提供了各种语法和工具方便程序员在单进程的前提下编写异步代码。这不是一条独特的道路。总结我喜欢JavaScript这门语言,它简单明了,容易上手。虽然平时工作中用到它的机会不多,但它总能在我需要的时候帮我快速解决问题。也因为它的灵活性,有一些隐藏的坑,一不小心就可能踩进去。我的建议是谨慎使用第三方库,多写测试用例。https://www.bilibili.com/video...本文参加了SegmentFault思维写作挑战赛,欢迎正在阅读的你加入。
