JavaScript 需要清楚的10件事

标签: javascript 需要 | 发表时间:2014-05-02 00:58 | 作者:天梯梦
出处:http://www.iteye.com

文/谢传贵

 

    在学习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

简介:传播原创高质量的技术内容

 

转自: http://chuansongme.com/n/172780



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [javascript 需要] 推荐:

JavaScript 需要清楚的10件事

- - Web前端 - ITeye博客
    在学习JavaScript的过程中,最需要搞清楚的10件事是什么. 关于这个问题有人在 Quora上给出了的答案. 其中提到了一些很有代表性的知识点(坑),但描述比较杂乱. 下面我将在他的基础上进行重新编排和解释. 希望对你学习 JavaScript有些帮助(为避免文章跑题,以下内容先不考虑ES5的 strict mode):.

Javascript诞生记

- Milido - 阮一峰的网络日志
二周前,我谈了一点Javascript的历史. 今天把这部分补全,从历史的角度,说明Javascript到底是如何设计出来的. 只有了解这段历史,才能明白Javascript为什么是现在的样子. 我依据的资料,主要是Brendan Eich的自述. "1994年,网景公司(Netscape)发布了Navigator浏览器0.9版.

JavaScript,你懂的

- dylan - keakon的涂鸦馆
经常有人问我,JavaScript应该怎么学. 先学基本语法,如果曾学过C等语言,应该1小时内就能掌握了. 再去使用内置的函数、方法和DOM API,熟悉它能干什么;而在学习DOM API的过程中,你还不得不与HTML和CSS打交道. 然后弄懂匿名函数和闭包,学会至少一个常用的JavaScript库(例如jQuery).

Javascript 里跑Linux

- rockmaple - Shellex&#39;s Blog
牛逼到暴的大拿 Fabrice Bellard,用Javascript实现了一个x86 PC 模拟器,然后成功在这个模拟器里面跑Linux(请用Firefox 4 / Google Chrome 11打开,Chome 12有BUG). 关于这个东西… 伊说 “I did it for fun“,大大啊大大啊….

高效 JavaScript

- xtps - ITeye论坛最新讨论
传统上,网页中不会有大量的脚本,至少脚本很少会影响网页的性能. 但随着网页越来越像 Web 应用程序,脚本的效率对网页性能影响越来越大. 而且使用 Web 技术开发的应用程序现在越来越多,因此提高脚本的性能变得很重要. 对于桌面应用程序,通常使用编译器将源代码转换为二进制程序. 编译器可以花费大量时间优化最终二进制程序的效率.

你得学JavaScript

- 蒋冰 - 伯乐在线 -博客
  注:本文由 敏捷翻译 - 蒋少雄 翻译自 Kenny Meyers 的博文.   如果三年前你问我应该学什么语言,我会告诉你是Ruby.   如果你现在想学一门语言的话,你应该学习JavaScript..   我认为,每一位Web开发人员都应该学习JavaScript. 目前推出的许多新技术都支持这个观点.

javascript 贪食蛇

- Xin - 博客园-首页原创精华区
我的程序用javascript与Html中的table结合,实现的简单的贪食蛇游戏,游戏的主要特点,可调整蛇移动速度,可调整蛇移动范围,碰壁、咬到身体则“Game Over. 游戏并不完善,只是实现了主要的功用,有设计不合理的地方,欢迎您感大家提意见.        实现方法:由javascript语言中的setInterval方法驱动整个游戏程序,设置“nowDirection”即蛇的当前移动方向为全局变量,由setInterval方法定时获取蛇的移动方向,由document.onkeydown()捕捉当前按键(上、下、左、右)以修改nowDirection,这样就可以用方向按键控制蛇周期时间的定向移动.

你不懂Javascript

- 英建 - 黑客志
过去几年我注意到技术圈一个很奇怪的现象,有太多程序员将那些他们只是有过非常浅显的了解,但其实根本就不懂的技术写到他们的简历中,这个现象几乎每种语言都有,但这其中最严重的就要数Javascript了. 出现这种状况的一个很大的原因就是现如今几乎每个开发者的工作都或多或少要依赖于Javascript,但大多数人并不真的理解这门语言,他们常用的学习方式是复制粘贴,使用这种方式,你永远不会真正学会这门语言,而只能得到一个你已经懂了的假象.

Javascript 中的 var

- - 酷壳 - CoolShell.cn
MelonCard发布了一篇文章——” how one missing var ruined our launch“(”少写了一个var毁了我的网站”),这篇文章是说MelonCard用Node.js做后台,因为出了一个小高峰——有50-100人注册,结果整个网站都不响应了,而且还出现了很多奇怪的问题.

JavaScript 基础

- - CSDN博客推荐文章
JavaScript可以出现在HTML的任意地方,甚至在之前插入也不成问题,使用标签. 不过要在框架网页中插入的话,就一定要在之前插入,否则不会运行. JavaScript对数据类型要求不严格,一般来说,声明变量的时候不需要声明类型,而且就算声明了类型,在使用过程中也可以给变量赋予其他类型的值,声明变量使用var关键字.