恰逢毕业论文准备时期,前端学习落下一段距离,今天借JavaScript的背景知识总结以将本人从环境领域拉回到计算机领域。
首先,JavaScript是一种有函数优先的轻量级、解释型或及时编译型的编程语言,大多数用于开发Web页面的脚本语言,同时也会被用于许多非浏览器环境中,其基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式和声明式的风格。它没有“子类”和“父类”的概念,也没有“类”(class)和“实例”(instance)的区分,而是靠一种独特的“原型链”(prototype chain)的模式来实现继承。
一、JavaScript的诞生
1994年,网景公司(Netscape)发布了Navigator浏览器9.0版,但是这个版本的浏览器只能用于浏览,而不具备判断用户是否互动成功的能力,只能依靠服务器来判断访问者的互动,占用大量的时间和服务器资源。因此,网景公司急需一种网页脚本语言,来让浏览者与网页进行互动。
此时,由工程师Brendan Eich负责开发这种新的语言。而当时恰逢面向对象编程(object-oriented programming)最兴盛的时期,所以Brendan开发的新语言受其影响很深,最明显的特征就是JavaScript的所有数据类型都是对象(object)。
由于必须有一种机制将所有对象联系起来,所以Brendan将new命令引入JavaScript用来从原型对象生成一个实例对象,并进行简化,使new命令后面跟的不是类,而是构造函数。但是这样也存在缺点,那就是无法共享属性和方法,每一个实例对象都有自己的属性和方法的副本,那就造成了极大的资源浪费。
为了解决这个问题,Brendan为构造函数设置一个prototype属性,这个属性包含一个对象,所有实例需要共享的属性和方法都放在这个对象里面,而不需要共享的属性和方法就放在构造函数中。
总的来说,Brendan的设计思路是:
- 借鉴C语言的基本语法;
- 借鉴Java语言的数据类型和内存管理;
- 借鉴Scheme语言,将函数提升到“第一等公民”(first class)的地位;
- 借鉴Self语言,使用基于原型(prototype)的集成机制。
总的来说,JavaScript语言实际上是(简化的)函数式编程+(简化的)面向对象编程的混合产物。
函数式编程(英语:functional programming)或称函数程序设计、泛函编程,是一种编程范式,它将电脑运算视为函数运算,并且避免使用程序状态以及易变对象。其中,λ演算为该语言最重要的基础。而且,λ演算的函数可以接受函数作为输入参数和输出返回值。
面向对象程序设计(英语:Object-oriented programming,缩写:OOP)是种具有对象概念的编程典范,同时也是一种程序开发的抽象方针。它可能包含数据、特性、代码与方法。对象则指的是类(class)的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性,对象里的程序可以访问及经常修改对象相关连的数据。
二、JavaScript的缺陷
缺陷产生原因
- 设计阶段过于仓促
整个JavaScript的设计时间只用了十天,其设计初衷知识为了解决一些简单的页面交互问题,而不是针对一些复杂应用的需要(如设计Gmail等)。
- 没有先例
JavaScript同时结合了函数式编程和面向对象编程的特点,到目前为止其依然是世界上唯一一种使用Prototype继承模型的主要语言。
- 过早地标准化
JavaScript的规格还没有来得及调整,就已经固化了,其在推出仅仅一年半之后就已经发布第一个国际标准ECMA-262,相比之下C语言在问世20年后才发布国际标准。
缺陷举例
- 不适合开发大型程序
JavaScript没有名称空间(namespace),比较难模块化;没有任何将代码分布在多个文件规范中,;允许同名函数的重复定义,后面的定义可以覆盖前面的定义,不利于模块化加载。
- 非常小的标准库
JavaScript提供的标准函数库非常小,只能完成一些基本操作,很多功能都不具备。
- null和underfined
null属于对象(object)的一种,意思是该对象为空,underfined则是一种数据类型,表示未定义。
typeof null; // object
typeof underfined; // underfined
二者比较容易混淆,并且意义完全同。
var foo;
alert(foo == null); // true
alert(foo == underfined); // true
alert(foo == null); // false
alert(foo == underfined); // true
- 全局变量难以控制
JavaScript的全局变量,在所有的模块中都是可见的,任何一个函数内部都可以生成全局变量,这大大加剧了程序的复杂性。
a = 1
(function(){
b=2;
alert(a);
})(); // 1
alert(b); //2
- 自动插入行尾分号
JavaScript中的所有语句都必须以分号结尾,但是如果忘记加分号,解释器并不会提醒,而是为你自动加上分号,有时候这会导致一些难以发现的错误。
- 加号运算符
+号作为运算符,有两个含义,可以表示数字与数字的和,也可以表示字符与字符的链接。如果一个操作项是字符,另一个操作项是数字,则数字自动转化为字符,这样的设计不必要地加剧了运算的复杂性。
- NaN
NaN是一种数字,表示超出了解释器的极限,它具有一些奇怪的特性:
NaN === NaN; //false
NaN !== NaN; //true
alert( 1 + NaN ); // NaN
- 数组和对象的区分
由于JavaScript的数组也属于对象,所以要区分一个对象是不是数组相当麻烦。
- == 和 ===
==用来判断两个值是否相等,当两个值类型不同时,会发生自动转换,得到的结果非常不符合直觉,任何时候都更推荐使用"==="精确判断比较符。
- 基本类型的包装对象
JavaScript的三种基本数据类型:字符串、数字和布尔值。它们都有相应的建构函数,可以生成字符串对象、数字对象和布尔值对象。与基本数据类型对应的对象类型作用很小,还很容易混淆。
总结
最后,总的来说,JS是历史的选择,它的编程能力很强大,它是目前网页编程的唯一语言,只要互联网发展,它就必然一起发展。还可以使用一些扩展项目扩展其用途,比如使用node.js可以使其用于后端的服务器编程,使用coffeeScript可以用python和ruby的语法。
本教程主要参考了《阮一峰的网络日志》。