文/谢传贵
在学习JavaScript的过程中,最需要搞清楚的10件事是什么?关于这个问题有人在 Quora上给出了的答案。其中提到了一些很有代表性的知识点(坑),但描述比较杂乱。下面我将在他的基础上进行重新编排和解释。希望对你学习 JavaScript有些帮助(为避免文章跑题,以下内容先不考虑ES5的 strict mode):
1. 使用关键字var声明变量
要使用一个变量,应该先声明它。在JavaScript中,声明变量非常简单,因为你不用关心它的类型。
1 |
function setLocal () {
|
2 |
var name = 'Tom' ;
|
3 |
alert( 'the name is ' + name);
|
4 |
} |
5 |
setLocal(); // "the name is Tom"
|
如果不用var呢?让我们来看一个例子:
01 |
var sex = 'female' ;
|
02 |
function setGlobal () {
|
03 |
var age = '86' ;
|
04 |
name = 'John' ;
|
05 |
sex = 'male' ; //我们不知函数外也有一个变量sex
|
06 |
alert(name + ' is ' + age + ' years old.' );
|
07 |
} |
08 |
setGlobal(); // "John is 86 years old."
|
09 |
alert(name); // "John"
|
10 |
alert(sex); // "male"
|
11 |
alert(age); // ReferenceError: age is not defined
|
在 这个例子中,从setGlobal函数外部我们能够访问(可读写)变量name而不能访问变量age。事实上,函数内部使用var声明的变量是局部变量, 只有函数内部能够访问。但由于没有使用var声明变量name,从函数外部也能访问到它 ,这很不安全。同时,事例代码中还试图声明变量sex,仍然由于没有使用var,却无意将外部变量sex的值覆盖了,即污染了其他代码,这更是难以接受 的。
特别地,在使用一个未声明的变量时,程序将会报错;使用一个已声明而未赋值的变量时,或者使用一个并不存在的对象属性时,返回的值是undefined:
1 |
var name;
|
2 |
var obj = {};
|
3 |
alert(name); // undefined
|
4 |
alert(obj.prop); // undefined
|
5 |
alert(some); // ReferenceError: some is not defined
|
总结:在声明一个变量时省去var,这个变量将变成一个全局变量(global variable),你程序的数据直接暴露给了全局,同时也可能覆盖函数外已有的同名变量,对他人代码构成了风险。所以,请一定记得使用关键字var。
2.单引号和双引号没有区别
一些传统的后端语言是明显区分单引号和双引号作用的,例如Java里表示字符需要使用单引号,而表示字符串需要使用双引号:
1 |
Char ch = 'a' ;
|
2 |
String str = "Cat" ;
|
然 而JavaScript没有char这样的数据类型,要表示文本数据类型,只能使用字符串(string)。创建字符串直接量最简单的方法是使用一对单引 号或双引号括起来你想表示的字符序列。选择使用单引号还是双引号从语法上没有区别,如果选择单引号,则字符串内部的单引号需要转义,如果选择双引号,则字 符串内部的双引号同理也需要转义。要表示单个字符,须使用长度为1的字符串。例如:
1 |
var name = "She said, \"Who is the president?\"" ;
|
2 |
var desc = 'What\'s that?' ;
|
3 |
var desc = 'e' ;
|
基于上面提到的转义关系,我个人比较喜欢使用单引号,这可以减少许多转义的麻烦,尤其是当你的代码中包含HTML代码时。试想如果下面的字符串选用双引号,那将增加很多反斜杠,而且还容易错:
1 |
$( 'div' ).append('
|
2 |
error info |
3 |
'); |
同理,如果HTML标签里嵌入JavaScript代码,也一样能减少反斜杠(不过,应尽量少在HTML标签上写JavaScript代码):
3.除了null和undefined,一切都像是对象(object)
JavaScript 的变量类型可以分为两类:原始类型(primitive types)和对象类型(object types)。原始类型有5种,分别是数字、字符串、布尔型,以及null和undefined两个特殊值。除了原始类型,其他的一切都是对象类型。除了 null和undefined,其他一切都“像是对象”。为什么说像是对象,因为接下来你会发现原始类型变量也能调用方法或属性,甚至连函数也拥有方法。
1 |
function f () {
|
2 |
var n = 10;
|
3 |
alert(n.toString()); // "10"
|
4 |
} |
5 |
f.call(); // f是一个函数,依然能调用方法
|
我 们看到,n是一个原始类型的值,而f是一个函数,他们都可以调用方法,就像一个对象一样。事实上,在JavaScript中,除了null和 undefined,一切都可以调用方法或属性。这里有一个隐藏的逻辑,那就是当原始类型的变量试图调用方法或属性时,它会被动态地转成其对应的包装对 象。让我们来检测一下:
1 |
function f () {
|
2 |
var n = 123;
|
3 |
Number.prototype.toString = function () {
|
4 |
return typeof this ;
|
5 |
}
|
6 |
alert( typeof n); //"number"
|
7 |
alert(n.toString()); //"object"
|
8 |
} |
9 |
f(); |
4.undefined, null, 0, NaN, ''在作为布尔值使用时都代表false
当处于布尔环境时,undefined, null, 0, NaN, ''会被作为false使用,其他的一切作为true使用。
1 |
if (o) {
|
2 |
//当o的值不为undefined, null, 0, NaN, '', false时,进入该处
|
3 |
} |
要注意,这里的字符串是一个长度为1的空字符串。
5.使用全等号===
JavaScript中有两个判断相等的运算符:==(一般相等)和===(全等)。一般相等运算符由2个等号组成,使用它进行相等判断时会对运算符两边的值进行类型转换,以使两边类型相同后再进行相等比较。例如:
1 |
0 == '' // true
|
2 |
0 == '0' // true
|
3 |
1 == true // true
|
4 |
false == '0' // true
|
5 |
null == undefined // true
|
6 |
' \t\r\n ' == 0 // true
|
正如上面的例子,由于会自动进行类型转换,一些我们直觉不会相等的值也相等了,这些结果大部分时候不是我们想要的。如果你想了解转换规则,推荐你看《ECMAScript. Equality operators.》,不过相当枯燥难记。
全 等运算符由3个连续的等号组成,使用它进行相等判断时不会对运算符两边的值进行类型转换,要满足相等,它不仅要求类型相同,还要求值相同,所以使用全等运 算符时上面的例子一个也不会相等。这里有一个特例,那就是NaN,它是唯一一个不与任何值相等的值,甚至包括它本身,要判断一个值是否等于NaN,你需要 使用全局函数isNaN:
1 |
NaN === NaN // false
|
2 |
isNaN(NaN) // true
|
所以,除非你很确定两个待比较值的类型是一样的,或者你很熟悉类型转换关系,否则我还是劝你使用全等号吧。
6.没有块作用域(block scope)
JavaScript 中没有块作用域或类作用域的概念,只有函数作用域,即函数内部定义的变量对于整个函数体以及函数内嵌套的函数都是可见的,而对于函数体外部是不可见的,与 花括号没有什么关系。例如下面的例子中变量i是定义在if条件的花括号代码块中的,我们依然能从花括号外访问:
1 |
function f () {
|
2 |
var c = 1;
|
3 |
if ( true ) {
|
4 |
var i = 2;
|
5 |
alert(c); // 1
|
6 |
}
|
7 |
alert(i); // 2
|
8 |
} |
正是因为JavaScript只有函数作用域,所以我们可以通过函数来模拟实现私有属性。
7.变量声明会被提升到当前作用域的顶部
什么意思呢?还是先来看一个例子(参考犀牛书第6版):
1 |
var scope = 'global' ;
|
2 |
function f () {
|
3 |
alert(scope); // "undefined", not "global"
|
4 |
var scope = 'local' ;
|
5 |
alert(scope); // "local"
|
6 |
var name = 'country' ;
|
7 |
} |
8 |
f(); |
结 合前面的知识,你也许认为函数第一行会打印"global",因为var声明和赋值发生在其后面,而函数外已经有scope变量了。听起来很和逻辑。事实 却是打印了"undefined"。这里涉及一个JavaScript很有趣的现象—提升(hoisting),函数内部声明的所有变量对整个函数作用域 都是可见的,就好像在函数执行时,所有的变量声明会被提升到第一行一样。上面的代码等效于:
1 |
var scope = 'global' ;
|
2 |
function f () {
|
3 |
var scope, name;
|
4 |
alert(scope); // "undefined"
|
5 |
scope = 'local' ;
|
6 |
alert(scope); // "local"
|
7 |
name = 'country' ;
|
8 |
} |
所以,在定义一个函数时,请将所有变量声明放在函数的第一行,因为这样的代码比较真实地反映了变量声明的提升现象。同时,即使你已理解了提升现象,但阅读代码的人不一定理解,为了避免困惑,从代码的可阅读性上仍然推荐将所有的变量声明置于函数作用域的顶部。
8.函数的参数可以被省略
这个很好理解。函数声明时可以指定形参的个数,但调用时并不强求传参的个数。在调用时,如果对应形参的位置没有给值,则其值为undefined。
1 |
function hello (name, age) {
|
2 |
alert( 'name is : ' + name + ', age is ' + age);
|
3 |
} |
4 |
5 |
hello( 'Anon' , 42); // name is : Anon, age is 42
|
6 |
hello( "Baptiste" ); // name is : Baptiste, age is undefined
|
7 |
hello( "Bulat" , 24, 42); // name is : Bulat, age is 24
|
9.JavaScript是面向对象的语言,使用原型继承机制
JavaScript是一门面向对象的语言,使用基于原型的继承机制(原型编程),不存在类(class)的概念。使用JavaScript实现继承非常简单。
01 |
if ( typeof Object.create != 'function' ) { //为低版本JavaScript提供create方法
|
02 |
Object.create = function (o) {
|
03 |
function F() {}
|
04 |
F.prototype = o;
|
05 |
return new F();
|
06 |
};
|
07 |
} |
08 |
var a = { };
|
09 |
a.foo = 'hello' ;
|
10 |
a. do = function () { alert( 'do something.' ); };
|
11 |
var b = Object.create(a); //对象b继承自对象a
|
12 |
b.bar = 'crazy' ;
|
13 |
b.bar // "crazy" b创建了自己的属性bar
|
14 |
b.foo // "hello" b从a继承了属性foo
|
15 |
b. do (); // "do something." b从a继承了方法do
|
16 |
b.foo = 'world' ;
|
17 |
b.foo // "world"
|
18 |
a.foo // "hello" // b创建了自己的属性foo, 这不会修改a的属性foo
|
19 |
a. do = function () { alert( 'i am a letter.' ); };
|
20 |
b. do (); // "i am a letter." a的方法do被更新,b动态响应了更新。
|
从 上面这个简短的示例可以看到,对象a直接从对象b继承了属性和方法,并且之后若是a有修改,b也动态更新继承。这个过程没有class什么事,一切都是对 象,按照Douglas Crockford的说法:“还有什么能比这更面向对象的呢?”(What could be more object oriented than that?)
10.JavaScript不仅限于浏览器
随着Web的发展,JavaScript在浏览器端可谓春风得意,但JavaScript绝不仅限于浏览器,它还可以用在其他地方,比如最近风头正劲的Node.js就是运行于服务器端的。
【嘉年华推荐】
也许你是一位后端工程师,日常使用的语言具有很完善的预检查能力,任何以上提到的语法错误都不会被IDE和编译器放过,但由于JavaScript通常运行在客户端,加上一些历史的原因,它并没有严格的预检查能力,所以良好的编程习惯是很重要的。
要学好一门语言当然不是掌握10点或20条就能做到的,这需要我们持续的学习和实践。若你有更好的建议,欢迎回复补充分享。
--
微信名称:阿里技术嘉年华
微信号:alibabatech
简介:传播原创高质量的技术内容
相关推荐
实现“图片先模糊后清楚”通常有两种主要方法:CSS渐进增强和JavaScript动态替换。 1. CSS渐进增强: 这种方法利用CSS的`filter`属性来模糊图片,配合CSS的`background-size`属性控制图片的显示大小。初始时,我们...
该文档仅是Javascript内置对象与函数的API说明文档,当你不清楚某JS函数的意义或参数含义时,查阅它将会相当方便。 如果你是对javascript没有任何基础的小菜,就不要下载它了,因为它并非JavaScript教程,下载了你...
内容 绝对清楚 当然了 因为我只是个初学者,感觉很适合初学者,拿出来和大家共享一下,另外还有这份教程对应的源文件,期待着能给您的学习也能带来帮助,至于这个教程的视频太大,无法上传在上面,所以感觉有些可惜.....
和其他的Missing Manuals图书不同,《JavaScript实战手册》清楚、精炼,手把手地讲解。 现代Web站点需要发布的东西远不仅仅是文本。访问者期待智能化的表单、导航标签页、弹出式帮助屏幕,以及交互式的照片集。...
和其他的Missing Manuals图书不同,本书清楚、精炼,手把手地讲解。 现代Web站点需要发布的东西远不仅仅是文本。访问者期待智能化的表单、导航标签页、弹出式帮助屏幕,以及交互式的照片集。本书介绍用漂亮的样式...
从标签“lunar javascript JavaScript 资源”可以推断出,该资源主要面向JavaScript开发者,特别是那些需要在项目中引入农历计算功能的开发者。标签中没有提及其他编程语言或技术栈,因此可以假定该项目是完全用...
以任务驱动方式讲解,用实例引导读者习,只需21天,便可轻松掌握JavaScript编程。 基础知识→核心技术→典型实例→综合练习→项目案例 242个典型实例、1个项目案例、333个练习题 一线开发人员全程贴心讲解,...
作者讲解了JavaScript的发展现状、实用技巧以及未来趋势,辅以诸多代码示例,条理清楚、分析到位。本书展示了更新颖、更巧妙、更有深度的JavaScript技术,同时理清了JavaScript的发展脉络,既能磨炼技能,又可开拓...
自己手写一个tree实例,tree实现其实很简单,主要先弄清楚html如何显示tree,可以先查看html元素,会发现tree的每个节点都是...然后使用javascript操作dom,例子中有些使用javascript的面向对象,tree计算核心为递归。
相信通过这篇文章一定能够清楚的认识到原型,现在就开始原型之旅吧。 认识原型 开始原型的介绍之前,首先来认识一下什么是原型? 在JavaScript中,原型也是一个对象,通过原型可以实现对象的属性继承,JavaScript的对象...
很实用的!关于JavaScript的语法讲的特别的清楚!而且文件也比较小!
目前River Trail还是作为一个Firefox浏览器扩展存在的,尚不清楚是否会引起其他厂家的注意并引入到各自的Javascript引擎中,例如V8。另外, 在原文的评论部分,Intel还解释了River Trail和Web Workers的不同,并欢迎...
JavaScript是一种广泛应用于网页和网络应用开发的脚本语言,它主要负责实现客户端的交互效果和动态功能。在“javascript做的鱼儿移动”这个项目中,我们可以理解为开发者使用JavaScript来模拟鱼儿在屏幕上的游动行为...
3. **导出图片**:对于需要分享或记录的解析结果,Regulex提供了将图表导出为图片的功能,方便在报告、教程或讨论中使用。 4. **学习与调试**:通过使用Regulex,开发者可以逐步掌握正则表达式的规则和技巧,同时也...
对于JavaScript的调试,首先需要进行调试前的准备工作,这包括在IE浏览器中启用脚本调试功能。这通常涉及取消“禁用脚本调试”的设置,以便在遇到问题时能够追踪和修复错误。调试时,可以通过“查看”菜单选择“脚本...
JavaScript验证框架是用于在前端进行数据验证的一种工具,它能够帮助开发者确保用户输入的数据符合预设的规则,提高用户体验并减少服务器端的压力。这个框架主要应用于表单验证,包括但不限于电子邮件地址、手机号码...
以任务驱动方式讲解,用实例引导读者习,只需21天,便可轻松掌握JavaScript编程。 基础知识→核心技术→典型实例→综合练习→项目案例 242个典型实例、1个项目案例、333个练习题 一线开发人员全程贴心讲解,...
下载须知:英文版,但是内容是真的清楚,超清....... Reacting to the Virtual World 1 Tired of thinking of the Web in terms of passive pages? Been there, done that. They’re called books. And they’re ...