第四章 变量、函数和运算符

  • A+
所属分类:Web前端
摘要

变量value在声明之前参与了运算,这是完全合法的,尽管这样会造成result的计算结果是一个特殊值NaN。这是因为JavaScript中有变量提升机制,也就是将两个var语句提前至函数的顶部,相当于


变量、函数和运算符

变量声明

function doSomething() {          var result = 10 + value;     var value = 10;     return result; } 

变量value在声明之前参与了运算,这是完全合法的,尽管这样会造成result的计算结果是一个特殊值NaN。这是因为JavaScript中有变量提升机制,也就是将两个var语句提前至函数的顶部,相当于

function doSomething() {          var result;     var value;          result = 10 + value;     value = 10;          return result; } 

变量声明提升意味着:在函数内部不管任何地方定义的变量和在函数顶部定义变量是完全一致的,因此,一种流行的风格就是将所有变量声明放在函数的顶部而不是散落在各个角落。简而言之,依照这种风格写出来的代码逻辑和JavaScript引擎解析这段代码的习惯非常的相似

作者推荐这种写法,并且推荐在函数顶部使用单var语句

function doSomething() {          var value = 10,         result = value + 10,         i,         len;          for (i = 0, len = items.length; i < len; i++) {         console.log(items[i]);     }   } 

推荐合并var语句,这可以让你的代码更短,下载更快

函数声明

和变量声明一样,函数声明也会被JavaScript引擎提前。因此,在代码重函数的调用可以出现在函数声明之前。

不好的做法:先使用后声明

doSomething();   function doSomething() {     console.log("hello word") } 

这段代码是可以正常运行的,因为JavaScript引擎将这段代码解析为:

function doSomething() {     console.log("hello word") }  doSomething(); 

由于JavaScript的这种行为,我们推荐总是先声明JavaScript函数然后在使用函数。Crockford的编程规范里包含这种设计,而且还推荐在声明变量之后就声明

function doSomethingWithItems(items) {     var i, len,         value = 10,         result = value + 10;          function doSomething(item) {         // 代码逻辑     }         for (i = 0, len = items.length; i < len; i++) {         doSomething(items[i]);     }   } 

不好的写法:在语句块内声明函数

if (flag) {     function doSomething() {         alert("Hi");     } } else {     function doSomething() {         alert("Yo!");     } } 

这段代码不会按照我们的意图执行,这段代码在不同浏览器中的运行结果也是不尽相同。不管flag的计算结果如何,大多数浏览器都会自动使用第二个声明。而Firefox则根据flag的计算结果选用合适的函数声明。这种场景是ECMAScript的一个灰色地带,应尽可能的避免

函数调用间隔

推荐写法: 在函数名和左括号之间没有空格,这样做是为了将它和块语句区分开来

// 好的写法 doSomething(item);  // 不好的写法 doSomething (item);  // 用来做比较的块语句 while (item) {     // 代码逻辑 } 

立即调用的函数

推荐使用()包裹住自执行函数

var value = (function() {     // 函数体          return {         message: "Hi"     } }()) 

严格模式

"use strict",这条编译指令不仅仅适用于全局,还是适用于局部,比如一个函数内。但是不推荐将"use strict"用在全局作用域中,因为这会让文件中的所有代码都以严格模式解析,所以如果将11个文件合并为一个文件时,当其中一个文件在全局作用域中启用了严格模式,那么所有代码都会以严格模式解析,这样非严格模式下的代码就会报错

// 不好的写法 "use strict"; function doSomething() {     // 代码 }  // 好的写法 function doSomething() {     "use strict";     // 代码 }   // 好的写法 : 多个函数使用严格模式 (function() {     "use strict";          function doSomething1() {         // 代码     }       function doSomething2() {          // 代码     } })(); 

相等

由于JavaScript有强制类型转换机制,JavaScript中的判断相等操作是很微妙的。如果不知道== 和 != 的比较规则,可以看看这篇第一章 JavaScript简介,由于这种微妙,所以推荐使用=== !== 进行判断

eval()

eval()的参数是一个字符串,eval()会将传入的字符串当做代码来执行。开发者可以通过这个函数载入外部的JavaScript代码,或随即生成JavaScript代码并执行它

eval("alert('Hi!')");  var count = 10; var number = eval("5 + count"); console.log(number); // 15 

在JavaScript中不止eval()有这样的功能,使用Function构造函数也可以做到这一点,setTimeout()和setInterval()也可以

var myfunc = new Function("alert('Hi!')");  setTimeout("document.body.style.background='red'", 50);  setInterval("document.title = 'It is now '" + (new Date()), 1000); 

严格模式下对eval()有着严格的限制,禁止在一个封闭的作用域中使用它创建新的变量或者函数。这条限制帮助我们避免了eval()的先天安全漏洞(严格模式下,传入eval()的字符串无法在调用函数所在的上下文声明变量或函数,非严格模式下是可以这样做的),尽量少使用eval(),不使用Function,setTimeout,setInterval

原始包装类型

JavaScript中的一个不易被了解且常常误解的方面是,这门语言对原始包装类型的依赖。JavaScript里的有3原始包装类型:String,Boolean,Number。每种类型都代表全局作用域中的一个构造函数,并分别表示对各自对应原始值的对像。原始包装类型的主要作用是对原始值具有对象的行为

注:原始值本身不具有对象特征,比如1.toString()是报错的,

必须要

var a = 1;

a.toString();

var name = "Nicholas"; console.log(name.toUpperCase()); 

尽管name是一个字符串,是原始类型不是对象,但是你仍然可以使用toUpperCase()之类的方法,即将字符串当做对象来对待。这种做法之所以行得通,是因为在这条语句的表象背后JavaScript引擎创建了一个String类型的新实例,紧跟着被销毁了,当再次需要时就会又创建另一个对象。你可以通过给字符串增加属性来检验这种行为。

var name = "Nicholas"; name.author = true; console.log(name.author); // undefined 

第二行结束后,author属性就不见了。因为表示这个字符串的临时String对象在第二行执行完成后就销毁了

不好的写法

var name = new String("Nicholas"); var author = new Boolean(true); var count = new Number(10); 

最后

第一部分的内容总算是结束了,这部分主要是编码风格,从格式化,到注释然后在到语句的编写,最后一些特殊的代码编写,写这么多为了什么呢!!!主要还是要扼杀bug在摇篮中,后面将会在编码实践上进行编码上的规范