首页 > 代码库 > JS基础
JS基础
对于JS来说,首先我们需要承认,这是一门有明显缺陷的语言,一般我们把这种问题叫做边界问题。任何语言都有边界问题,而且仅仅是针对这一门语言存在的。但是JS的这些缺陷是如此的明显,以至于有人把它比喻成一把没有柄的剑,还没有伤到敌人,先让自己鲜血淋漓。
加载方式与全局变量
JS的加载方式和传统的基于编译的语言有着极大的不同,它是通过标签加载到浏览器中的,并在加载结束后就会立即运行,甚至有可能页面都没有完全的加载完成。HTML 页面中可能会有很多的script标签,当然,正如你所料到的,他们是按顺序加载并执行的。
写在HTML页面中的script标签是同步加载的。鉴于HTML页面在浏览器中被解释的方式,你甚至可以在JS里面直接使用document.write()
方法来向document中直接增加其他的script标签,这也是JS常用的一种同步加载其他JS脚本的方法。不过这种方法并不可取,不建议这么干。
JS也可以被异步的加载,异步的加载指的是在document完成之后所进行的加载。这种加载方式和同步加载的最大区别在于你需要自己保证JS被正确的加载了。方法有两种一种是自己通过某种方式验证,另一种是通过document.state来保证,不过后一种我觉得不太靠谱,因为对DOM(文档对象模型)的改动很多操作都有可能会导致这个对象的值得改变。JS的异步加载是AMD(Asynchronous Module Definition)的基础。
全局变量问题乍一听起来似乎没什么大不了的,但是如果你加载了好几个不同JS文件在你的页面里面那这就是一个问题。因为很容易冲突,这并不难想象。解决的方法也很简单,就是通过命名空间。当然JS是不支持这个技术的,只能通过对象和闭包来变通的实现。
闭包与面向对象
正如你所想象的那样,JS对于面向对象的支持实在是不咋地,不过比C语言还是要强一些。至少还有一个new语句可以让你来创建对象,不过还是建议使用工厂而不是使用new。一般来说,比较好的提供对象的方法是通过一个闭包来返回一个对象。这种做法在现代JS里面很常见。
var object=function(){ ... return { ... } }
这样做的原因其实也没什么,主要是比较直观,最大程度上的利用对象字面值,而且也能够提供一个闭包,这样可能处理私有的方法和属性,能够很好的做到数据的封装。
JS与DOM(文档对象模型)
首先要知道,JS和DOM是两回事。JS是一门编程语言,而DOM是文档对象模型,是由浏览器提供的。DOM一般会通过JS来进行操作,但是DOM并非JS的一部分。JS对DOM的操作是立即生效的。DOM中比较重要的对象有document和Element,还有window对象。
JS与异步
JS本身并不提供异步的支持,或者所谓的多线程的支持。不过据说新的JS标准里会提供worker,类似于swing的worker,用来对长时间的异步操作进行支持。
虽然JS本身不支持异步操作,但是我们可以通过window对象的setTimeout
或者setInterval
方法来模拟。
此外还要注意的是JS里面对于AJAX的操作和JS的加载往往是异步的。不过AJAX可以设置为同步加载,但是JS的加载是绝对的异步,这个需要在开发中特别的注意。还要注意的是,异步的加载JS的这种做法往往被用来实现跨域的功能。
JS与反射
JS有一定的反射能力,但不像java那样的明确。当然,主要是这个需求并不明显,一般来说都是需要进行lib开发可能才会需要。普通的操作显然不需要这个能力。而且JS是一种动态的语言,它的对象其内容往往可以很容易的扩展和重写,不过随意的更改对象中的方法显然是不可取的,这样会极大的影响代码的可读性。
我们需要注意的可能是call方法和apply方法。这些这两个方法可以对方法进行调用,同时都支持this对象的注入。这个功能其实很有用处,往往用来封装第三方的类库。这两个方法的差别在于给参的方式不同,call方法参数传递和直接调用方法一样,apply方法的参数传递使用的是数组。
而eval
方法往往是要避免使用的,但是特殊情况下还是需要使用。比如说的确获取到的是一段基于文本的JS片段。
JS基础