一篇博文将JavaScript尽收眼底
简介
这篇文章是为专业程序员介绍的JavaScript语言的,它是一种小巧的语言,如果你熟悉其他的编程语言,那么这篇文章对你来讲不是那么难以理解。
JavaScript不是Java,他们是两门完全不同的语言,JavaScript不是Java的子集,JavaScript不能被认为是Java(Java就是Java)。JavaScript分享了像Java一样分享C语言的语法,但从更深角度讲JavaScript更与Scheme和Self有相似之处。它是一门小巧的语言,但是它确实强大的和丰富的语言。你应该好好观察一下它,你会发现它不是一个玩具语言,而是一个拥有许多与众不同特性的、完整的语言。
JavaScript是一门不用花太多时间学习的正规语言。它能更好地适合一些任务,比如与Java相比它更适合客户端编程。以我的实践经验,我发现用JavaScript工作使我成为一个更好的Java程序员,因为它给我带来一套丰富的技巧。
当我最初接触JavaScript时,我没有理他以为它不值得我的注意。后来,我对它刮目相看,因为我发现隐藏在浏览器中的它是一个如此有效的程序语言。我最初是在JavaScript在Sun和Netscape公司的初始陈述注意到它的。他们对JavaScript做了许多错误陈述,以免使它和Java处于竞争的位置。这些错误陈述继续充斥这那些只为傀儡和业余爱好者提供的、不好的JavaScript书中。
历史
JavaScript是被Netscape的Brendan Eich,作为一个页面脚本语言,在Navigator 2中开发的。它是一个非常具有表现力的动态程序语言,因为和浏览器的关系,它立刻变的大红大紫了。它从来没有得到一个可以校正它的问题的和基于真正使用目的测试周期,这一切导致它很强大却也有缺陷。
这篇文章描述了ECMAScript 版本3 (也叫 JavaScript 1.5)。 Microsoft和Netscape一起开发了一个没有改正缺陷的呆滞版本。新版本的语言也许不能叫JavaScript,也不在这篇文章的讨论范围内。
数据类型
JavaScript包含一小套数据类型,它有3种简单的类型:boolean,number, 和 string;特殊的值:null,undefined;其他的所有基于object类型的变化。
布尔类型有2个值:true和false。
数字是64位的浮点值,与Java的Double类似。它没有整型。除法运算可能带来小数位的结果。数字包括特殊值NaN(不是一个数字)和Infinity。
字符串(string)是从零到多个Unicode字符组成的。没有单独的字节类型。一个字节被描绘成一个长度为1的字符串。字符串被'符号或"符号引用到一起,单引号和双引号可以替换使用,但必须前后匹配使用。
1 |
'This is a string.' |
2 |
"Isn't this a string? Yes!" |
3 |
'A' // The character A |
4 |
"" // An empty string |
转义用字符,就像Java一样。字符串是不可变的。字符串有一个length属性类查看字符串的用字符的个数。
print?
1 |
var s = "Hello World!" ; |
2 |
s.length == 12 |
可以给这些简单类型增加函数,你可以为所有数字类型增加一个int()的函数,当你调用Math.PI.int()的时候就会得到3这个结果。
一个实现可能提供其它类型,比如日期(Dates)类型,正则表达式类型,但是他们真正的类型是Object类型,所有其它类型都是Object类型。
对象
JavaScript拥有非常漂亮的符号便利以对付那些键值集合(哈希表)(hashtables)。
print?
1 |
var myHashtable = {}; |
这条语句了声明了一个键值集合,并把它分配到一个局部变量里。JavaScript是弱类型的,所以我们不能用类型的名称来进行声明。我们用索引的方式从键值结合中增加、替换和获取对象。
1 |
myHashtable[ "name" ] = "Carl Hollywood" ; |
也可以使用“.”的方式带来一点便利。
1 |
myHashtable.city = "Anytown" ; |
当索引是一个合法的系统保留字时,点符号就变得没用了。这是因为一个语言上的定义错误,保留字不能被用于点符号的形势下,但是可以用于索引的形式下。
你会发现JavaScript的哈希表符号与Java的对象和数组符号非常地相似。JavaScript把这更发扬广大了:对象和哈希表是一个回事,所以我可以这样写
1 |
var myHashtable = new Object(); |
这个结果确实是一样的。
用for语句可以实现对象一个枚举的能力。
1 |
for ( var n in myHashtable) { |
2 |
if (myHashtable.hasOwnProperty(n)) { |
3 |
document.writeln( "<p>" + n + ": " + myHashtable[n] + "</p>" ); |
4 |
} |
5 |
} |
这个结果应该是
1 |
<p>name: Carl Hollywood</p> |
2 |
<p>city: Anytown</p> |
一个对象就是一个涉及到键/值对的集合,键是字符串(或者其他的元素比如那些被转化为字符串的数字),值可以是任何数据类型,包括其他对象。对象经常以哈希表的方式实现,但是没有任何哈希表(比如哈希函数或重写的函数)天性的可见。
对象很容易被嵌套到别的对象当中,并且对象的表达式可以内容对象里使用。
1 |
this .div = document.body.children[document.body.children.length - 1]; |
对象的文字表达中,一个对象描述了包含在大括弧中的一组用逗点隔开的键/值对。键可以是在其后用冒号的标识符或字符串。由于语言定义的错误,系统预留字不能以标识符方式出现,但可以用字符串方式出现。值可以是任何类型的文字或表达式。
1 |
var myObject = {name: "Jack B. Nimble" , 'goto' : 'Jail' , grade: 'A' , level: 3}; |
2 |
return { |
3 |
event: event, |
4 |
op: event.type, |
5 |
to: event.srcElement, |
6 |
x: event.clientX + document.body.scrollLeft, |
7 |
y: event.clientY + document.body.scrollTop}; |
8 |
emptyObject = {}; |
JavaScript的对象模式是JSON的数据交换格式的基础。
新的成员可以在任何时候被附着增加到任何对象上。
1 |
myObject.nickname = 'Jackie the Bee' ; |
数组和函数以对象方式实现。
数组
JavaScript中数组也是哈希表对象,这使它非常好地与稀少的数组程序相称。当你声明了一个数组,你不需要声明它的大小,数组会自增长,这很像Java的向量(vectors)。数组的值根据键来定位,而不是根据偏移量,这使JavaScript数组非常方便地使用,但不适合那些数字分析应用。
对象和数组最主要的不同点是length属性。length属性总是比最大的整数键大1。有2种方式创建一个新数组。
1 |
var myArray = []; |
2 |
var myArray = new Array(); |
数组不是强类型,它可以包括数字、字符串、布尔值、对象、函数和数组,你可以在一个数组中混合使用字符串、数字和对象。你以嵌套序列的方式使用数组,这和s-expressions的方式非常地类似。数组的第一个索引通常用0。
当数组增加一个新元素的时候,它的索引是比数组长度。然后数组的长度变成在索引基础上加1。这个便利的特性使数组很容易在for循环中增加元素的数量。
数组有个与对象类似的符号标记。
print?
01 |
myList = [ 'oats' , 'peas' , 'beans' , 'barley' ]; |
02 |
03 |
emptyArray = []; |
04 |
05 |
month_lengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; |
06 |
07 |
slides = [ |
08 |
{url: 'slide0001.html' , title: 'Looking Ahead' }, |
09 |
{url: 'slide0008.html' , title: 'Forecast' }, |
10 |
{url: 'slide0021.html' , title: 'Summary' } |
11 |
]; |
新元素以分配的方式增加到数组中。
1 |
a[i + j] = f(a[i], a[j]); |
函数
JavaScript的函数看起来想C语言的函数一样,但JavaScript用function声明而不是类型关键字。当调用一个函数时,传递指定数目的参数不是必须的,过度的参数会被忽略,丢失的参数被赋值为undefined,这使写一个处理可选参数的函数变的很容易。
一个函数有权使用一个参数数组,这个数组包含了所有的实际上被调用传递进来的参数。这使处理一个带可变数目的参数变的很容易,例如:
print?
1 |
function sum() { // Take any number of parameters and return the sum |
2 |
var total = 0; |
3 |
for ( var i = 0; i < arguments.length; ++i) { |
4 |
total += arguments[i]; |
5 |
} |
6 |
return total; |
7 |
} |
JavaScript有内部函数,这与Java的内部类起了相同的作用,但是不是那么地明显。JavaScript也有也有扮演着lambda表达式的匿名函数。函数有词法上的作用域。
函数是对象的第一课,这意味着函数可以被存储在对象中,并且作为参数传递给其它函数。
定义函数
有3种方式定义一个函数:function声明,function操作符和function构造器。
function声明
function声明在当前的作用域内创建一个被命名的函数。
1 |
function name(argumentlist) block |
函数可以嵌套,必须闭合,有0个或多个以逗号隔开的参数名称。block是由0个或多个{ }附着着。
function声明以function操作符形式速记:
1 |
var name = function name (argumentlist) block ; |
function操作符
function操作符是一个产生一个对象的前缀操作符,它看起来和function声明很类似。
1 |
function name(argumentlist) block |
名称是可选的,如果提供了,那么可以用于函数的递归调用。这也用于访问函数的对象成员(除了IE以外)。如果名称被省略了,那么它就是一个匿名函数。
函数的操作符经常用于把它分配给一个原型(prototype)。
函数的操作符也经常用于在适当的地方定义函数,比迅速地得到当写回调的时候。( The function operator can also be used to define functions in-place, which is handy when writing callbacks.)
function构造器
function构造器携带字符包含在参数和内部,从而产生一个function对象。
1 |
new Function(strings...) |
不要使用这种方式,由于语言引用的惯例导致很难恰当的表达一个函数身体作为一个字符串。在字符形式中,早期的错误检查不起作用。这也是很慢的,因为编译器必须被触发每当构造器被调用的时候,并且这样浪费内存,因为每个函数需要它自己独立的实现。
对象和this
一个函数是一个对象,它可以包含成员就像其它对象一样。这就允许一个函数包含它自己的数据表,这也允许一个对象扮演一个“类”,包含构造函数和一套相关的函数。
一个方式可以是一个对象的成员,当一个函数是一个对象的成员的时候,被成为“方法”。有一个特殊的变量,叫做“this”,当一个对象的方式被调用时指向了对象。
例如:在表达式foo.bar()中,this变量就指向了对象foo,它作为了函数bar的一个额外的参数。函数bar可以使用this进入对象内部以找到有用的项目。
一个深一点的表示式do.re.mi.fa(),this变量指向了对象do.re.mi,而不是对象do。在一个简单的函数调用中,this指向了没有太大用的Global Object (也叫 window)。当调用一个内部函数时,正确的行为是保护好当前this的值。
构造器
当函数被用于初始化对象的时候被叫做构造器,调用一个构造器的次序与调用一个普通的函数有一些细微的不同。一个构造器带着new前缀被调用:
1 |
new Constructor(parameters...) |
根据习惯,构造器的名字的首字母使用大写的。
new前缀改变了this 的含义,不是平常的值,而是代表了“新对象”。构造器的身体将会初始化对象的成员。构造起将会返回一个新对象,除非明确的使用了return语句进行替换。
被构造的对象将会包含一个秘密的指向了构造器的prototype的成员的原型链接域。
原型(Prototype)
对象包含一个隐藏的连接属性,这个链接指向了prototype,就是构造器的实例。
当条目以点形式或索引形式从一个对象被访问的时候,如果条目没有在对象中被发现那么就检查他的链接对象,如果链接对象中也没发现,那么如果链接对象本身有一个链接对象,那么就继续检查这个链接对象,如果链接对象所有环节都检查完毕,那么就返回undefined。
原型用于链接住一系列的继承
成员可以用分配的方式增加到prototype中来,这我们定义一个类Demo,它从Ancestor继承,并增加了它独有的方法foo。
1 |
function Demo() {} |
2 |
Demo.prototype = new Ancestor(); |
3 |
Demo.prototype.foo = function () {}; |
变量
定义变量使用var语句。当变量在函数内部定义时,var有着函数范围(function-scope)级别,这个变量不能在函数外被访问。JavaScript中没有其他的范围域粒度了,更具体的说,JavaScript中没有块域(block-scope)。
任何在函数中使用但没有用var明确定义的变量,都会被假定属于全局对象。
任何没有被明确初始化的变量都会被赋值于undefined。
变量不是强类型的,一个变量引用一个对象、字符串、数字、布尔值、null值或者是undefined。
当函数被调用的时候会产生一套新的变量,这允许递归的调用。
闭合
函数可以被定义到其他函数中,内部函数有权使用在外部函数定义的变量,如果一个引用内部函数继续存在(例如一个回调函数),那么外部函数的变量也将继续存在。
返回值
JavaScript没有void类型,所以每个函数都必须返回一个值,除了构造器之外默认值是undefined,构造器的默认返回值是this
语句
语句包括 var, if, switch, for, while, do, break, continue, return, try, throw, and with,它们大多数与C类的语言相同。
var语句是一个或多个变量名称的列表,它们以逗号隔开,带着可选的初始化表达式。
1 |
var a, b = window.document.body; |
如果var语句出现在所有的函数之外那么就声明了一个全局的变量。如果出现在一个函数内,就声明了一个局部的变量。
在if语句,while语句,do语句, 和符合逻辑的操作符中,JavaScript视为false,null,undefined, ""(空字符串),和数字0作为假(false)。其它所有值被视为真(true)。
在switch语句中的case标记可以是表达式,它们不必非得是常数,也可以是字符串。
有2种形式的for语句,第一种像这样 (
init;
test;
inc)
形式。第二种是对象重复器。
1 |
for (name in object) { |
2 |
if (object.hasOwnProperty(name)) { |
3 |
value = object[name]; |
4 |
} |
5 |
} |
上面执行在object中的每一个name,名字产生的次序是不确定的。
语句可以有个前缀,就是一个标识符跟着一个冒号。
with语句不应该被使用
操作符
JavaScript有还算完整的操作符,大多数他们都与C类的语言工作的方式相同,但请注意一些细微的差异
+操作符用于加法和字符串联,如果任意操作数是字符串,那么进行串联,这可能会引起错误,比如说'$' + 3 + 4 会得到'$34',而不是'$7'。
+可以作为一个前缀操作符把字符操作数转化为数字。
!!可以作为一个前缀操作符,转化操作数为布尔值。
&&操作符,一般被称为“逻辑与”(logical and),它也被称为guard,如果第一个操作数是false、null、undefined、""(空字符串)或者数字0那么将返回第一个操作数,否则将返回第二个操作数。这提供了一个便利地测试null值的方法:
1 |
value = v || 10; /* Use the value of v, but if v |
2 |
doesn't have a value, use 10 instead. */ |
||操作符一般被称为“逻辑或”(logical or),它也被称为default,如果第一个操作数是false、null、undefined、""(空字符串)或者数字0, 那么将返回第二个操作数,否则返回第一个操作数。这提供了一个便利地设定默认值的方式:
value = v || 10; /* Use the value of v, but if v
doesn't have a value, use 10 instead. */
JavaScript支持一套逐位和移位的操作运算符,但却没有偶提供整型将他们应用。当一个数字操作数(一个64位浮点数)转化成32位整型的在运算之前,然后在转化回浮点数在操作在运算之后会发生什么呢?
在JavaScript中,void是一个前缀操作符,而不是一种类型,它总是返回undefined值。这仅仅有一点点价值,我提到它的原因是万一你不小心以习惯打出来它,而不会被它怪异的行为所迷惑。
typeof操作符返回一个基于它的操作数的字符串
错误产生了。
Object | 'object' |
Array | 'object' |
Function | 'function' |
String | 'string' |
Number | 'number' |
Boolean | 'boolean' |
null | 'object' |
undefined | 'undefined' |
杂目
全局对象
全局对象包含着所有的函数和所有的那些不在任何函数内定义的变量和对象,令人惊讶的是,全局变量在语言中并没有一个确切的名字。一些时候,this指向它,但大多数情况并不是的。在浏览器中window和self都是指向全局对象的全局对象成员,因此给了一个间接的对它的寻址方法。
如果一个变量可以被访问,但是没有在当前域下被找到,就会在全局对象范围查找,如果仍没有,就会返回错误。
ECMAScript规范没有谈论关于多个全局对象的可行性,或者上下文关系,但是浏览器支持这个,每个窗口都有它自己的全局对象。
分号的插入时机
这个语言的一个错误及时分号的插入,有一个技巧是用分号来终止语句。用各种开发工具去进行插入工作是合理的,没有必要为了语言的定义而让编译器去去做,请使用分号。
预留字
JavaScript对系统预留字的支持严重的过了头,这些预留字是:
print?
01 |
abstract |
02 |
boolean break byte |
03 |
case catch char class const continue |
04 |
debugger default delete do double |
05 |
else enum export extends |
06 |
false final finally float for function |
07 |
goto |
08 |
if implements import in instanceof int interface |
09 |
long |
10 |
native new null |
11 |
package private protected public |
12 |
return |
13 |
short static super switch synchronized |
14 |
this throw throws transient true try typeof |
15 |
var volatile void |
16 |
while with |
很大一部分这些关键字并没有在JavaScript中使用,一个预留字不可以在如下的方式下被使用:
- 作为一个对象名字标记
- 作为点形式的的成员
- 作为函数的参数
- 作为一个var
- 作为一个绝对的全局变量
- 作为一个语句标号(As a statement label)
前2个限制是不可原谅的,绝对不要使用。接下来的2个的使用可以被接受,但是这样使用是非常不牢靠的。
一篇博文将JavaScript尽收眼底的更多相关文章
- Visual Studio Code(VS code)你们都在用吗?或许你们需要看一下这篇博文
写在前面 在前端开发中,有一个非常好用的工具,Visual Studio Code,简称VS code. 都不用我安利VS code,大家就会乖乖的去用,无数个大言不惭的攻城狮,都被VS code比德 ...
- 【转】Visual Studio Code(VS code)你们都在用吗?或许你们需要看一下这篇博文
写在前面 在前端开发中,有一个非常好用的工具,Visual Studio Code,简称VS code. 都不用我安利VS code,大家就会乖乖的去用,无数个大言不惭的攻城狮,都被VS code比德 ...
- webIDE 第二篇博文
这是我做webIDE过程中的第二篇博文,之所以隔了这么长时间没更,因为确实是没有啥进度啊,没什么可写的,现在虽然依然没啥进度,但中途遇到很多坑,这些坑还是有记录下来的必要的. 因个人水平问题,可能有的 ...
- 你们都在用IntelliJ IDEA吗?或许你们需要看一下这篇博文
写在前面 以前一直用的elipce,如今入坑IntelliJ IDEA,没想到啊.深深的爱上了它,强大到无所不能: "工欲善其事必先利其器",IntelliJ IDEA作为一个非常 ...
- 看到篇博文,用python pandas改写了下
看到篇博文,https://blog.csdn.net/young2415/article/details/82795688 需求是需要统计部门礼品数量,自己简单绘制了个表格,如下: 大意是,每个部门 ...
- Spring整合Struts2框架的第一种方式(Action由Struts2框架来创建)。在我的上一篇博文中介绍的通过web工厂的方式获取servcie的方法因为太麻烦,所以开发的时候不会使用。
1. spring整合struts的基本操作见我的上一篇博文:https://www.cnblogs.com/wyhluckdog/p/10140588.html,这里面将spring与struts2 ...
- 关于InterruptedException的两篇博文的转载
博文一:https://www.jianshu.com/p/a8abe097d4ed InterruptedException异常 在了解InterruptedException异常之前应该了解以下的 ...
- 程序员小张的第一篇博文 --记Markdown的使用学习
1.前言 为了即将到来的面试做准备,以及记录一下平日里自己的学习过程和生活日常,我开始进驻博客园啦!这就是我的第一篇博客(有点小激动)~ 作为一只新手,首先记录一下今晚的编写博文的学习过程吧~ 2.使 ...
- .Net小白的第一篇博文
说起来也比较惭愧,5个月之前,我早已创建了博客园账号,那时候的我雄心壮志,给自己定下了 很多目标.现在回想起来,除了体重的增长,头发的稀疏,似乎这段时间的消逝并没有带给我什么见识上的成长.哈哈,想必大 ...
随机推荐
- 第3章 TCP协议详解
第3章 TCP协议详解 3.1 TCP服务的特点 传输协议主要有两个:TCP协议和UDP协议,TCP协议相对于UDP协议的特点是 面向连接使用TCP协议通信的双方必须先建立连接,完成数据交换后,通信双 ...
- Spring Boot 示例项目
Spring Boot 基于注解式开发 maven REST 示例项目 项目地址:https://github.com/windwant/spring-boot-service 项目地址: ...
- git 从头开始
下载安装git 打开git,输入以下命令,引号内的为你自己的名字和邮箱 git config --global user.name "Your Name"git config -- ...
- [SHELL]退出脚本
一,退出状态码 1,范围:0~255 2,查看退出状态码:必须在命令执行之后立即执行 ,显示的是脚本最后一条命令的退出状态码 echo $? 若f返回值为0,则表示正常 有异常为正值 二,exit 脚 ...
- 【第二章】Shell 变量
一.什么是变量? 变量就是一个固定的字符串(也可以是字符.数字的组合)代替更多.更复杂的内容,该内容可能是变量.路径.字符串等其他内容. 变量就是程序中保存用户数据的一块内存空间,而变量名就是这块内存 ...
- [2018 ACL Long] 对话系统
[NLG - E2E - knowledge guide generation] 1. Knowledge Diffusion for Neural Dialogue Generation ( Ci ...
- NMAP-主机扫描
1.全面扫描 2.扫描指定段 3.ping扫描 只进行ping操作,十分隐蔽 4.无ping扫描 适用于防火墙禁止ping 5.TCP SYN扫描 6.TCP ACK扫描 7.UDP扫描 8.ICMP ...
- Python面向对象-类成员
类的成员可以分为三大类:字段.方法和属性: 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的多少,在 ...
- 基于angular+bower+glup的webapp
一:bower介绍 1:全局安装安装bower cnpm i -g bower bower常用指令: bower init //初始化文件 bower install bower uninstall ...
- Alpha版——版本控制报告(Thunder)
Part One 回答问题: 0.在吹牛之前,先回答这个问题:如果你的团队来了一个新队员,有一台全新的机器,你们是否有一个文档,只要设置了相应的权限,她就可以根据文档,从头开始搭建环境,并成功地把最新 ...