JavaScript 开发的45个经典技巧

JavaScript是一个绝冠全球的编程语言,可用于Web开发、移动应用开发(PhoneGap、Appcelerator)、服务器端开发(Node.js和Wakanda)等等。JavaScript还是很多新手踏入编程世界的第一个语言。既可以用来显示浏览器中的简单提示框,也可以通过nodebot或nodruino来控制机器人。能够编写结构清晰、性能高效的JavaScript代码的开发人员,现如今已成了招聘市场最受追捧的人。

在这篇文章里,我将分享一些JavaScript的技巧、秘诀和最佳实践,除了少数几个外,不管是浏览器的JavaScript引擎,还是服务器端JavaScript解释器,均适用。

本文中的示例代码,通过了在Google Chrome 30最新版(V8 3.20.17.15)上的测试。

1、首次为变量赋值时务必使用var关键字

变量没有声明而直接赋值得话,默认会作为一个新的全局变量,要尽量避免使用全局变量。

2、使用===取代==

==和!=操作符会在需要的情况下自动转换数据类型。但===和!==不会,它们会同时比较值和数据类型,这也使得它们要比==和!=快。
  1. [10] === 10    // is false
  2. [10]  == 10    // is true
  3. '10' == 10     // is true
  4. '10' === 10    // is false
  5. []   == 0     // is true
  6. [] ===  0     // is false
  7. '' == false   // is true but true == "a" is false
  8. '' === false  // is false
复制代码
3、underfined、null、0、false、NaN、空字符串的逻辑结果均为false

4、行尾使用分号

实践中最好还是使用分号,忘了写也没事,大部分情况下JavaScript解释器都会自动添加。对于为何要使用分号,可参考文章JavaScript中关于分号的真相。

5、使用对象构造器
  1. function Person(firstName, lastName){
  2.     this.firstName =  firstName;
  3.     this.lastName = lastName;
  4. }
  5. var Saad = new Person("Saad", "Mousliki");
复制代码
6、小心使用typeof、instanceof和contructor

typeof:JavaScript一元操作符,用于以字符串的形式返回变量的原始类型,注意,typeof null也会返回object,大多数的对象类型(数组Array、时间Date等)也会返回object
contructor:内部原型属性,可以通过代码重写
instanceof:JavaScript操作符,会在原型链中的构造器中搜索,找到则返回true,否则返回false
  1. var arr = ["a", "b", "c"];
  2. typeof arr;   // 返回 "object" 
  3. arr instanceof Array // true
  4. arr.constructor();  //[]
复制代码
7、使用自调用函数

函数在创建之后直接自动执行,通常称之为自调用匿名函数(Self-Invoked Anonymous Function)或直接调用函数表达式(Immediately Invoked Function Expression )。格式如下:
  1. (function(){
  2.     // 置于此处的代码将自动执行
  3. })();  
  4. (function(a,b){
  5.     var result = a+b;
  6.     return result;
  7. })(10,20)
复制代码
8、从数组中随机获取成员
  1. var items = [12, 548 , 'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' , 2145 , 119];
  2. var  randomItem = items[Math.floor(Math.random() * items.length)];
复制代码
9、获取指定范围内的随机数

这个功能在生成测试用的假数据时特别有数,比如介与指定范围内的工资数。
  1. var x = Math.floor(Math.random() * (max - min + 1)) + min;
复制代码
10、生成从0到指定值的数字数组
  1. var numbersArray = [] , max = 100;
  2. for( var i=1; numbersArray.push(i++) < max;);  // numbers = [1,2,3 ... 100]
复制代码
11、生成随机的字母数字字符串
  1. function generateRandomAlphaNum(len) {
  2.     var rdmString = "";
  3.     for( ; rdmString.length < len; rdmString  += Math.random().toString(36).substr(2));
  4.     return  rdmString.substr(0, len);
  5. }
复制代码
12、打乱数字数组的顺序
  1. var numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411];
  2. numbers = numbers.sort(function(){ return Math.random() - 0.5});
  3. /* numbers 数组将类似于 [120, 5, 228, -215, 400, 458, -85411, 122205]  */
复制代码
这里使用了JavaScript内置的数组排序函数,更好的办法是用专门的代码来实现(如Fisher-Yates算法),可以参见StackOverFlow上的这个讨论。

13、字符串去空格

Java、C#和PHP等语言都实现了专门的字符串去空格函数,但JavaScript中是没有的,可以通过下面的代码来为String对象函数一个trim函数:
  1. String.prototype.trim = function(){return this.replace(/^\s+|\s+$/g, "");};
复制代码
新的JavaScript引擎已经有了trim()的原生实现。

14、数组之间追加
  1. var array1 = [12 , "foo" , {name "Joe"} , -2458];
  2. var array2 = ["Doe" , 555 , 100];
  3. Array.prototype.push.apply(array1, array2);
  4. /* array1 值为  [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */
复制代码
15、对象转换为数组
  1. var argArray = Array.prototype.slice.call(arguments);
复制代码
16、验证是否是数字
  1. function isNumber(n){
  2.     return !isNaN(parseFloat(n)) && isFinite(n);
  3. }
复制代码
17、验证是否是数组
  1. function isArray(obj){
  2.     return Object.prototype.toString.call(obj) === '[object Array]' ;
  3. }
复制代码
但如果toString()方法被重写过得话,就行不通了。也可以使用下面的方法:

Array.isArray(obj); // its a new Array method
如果在浏览器中没有使用frame,还可以用instanceof,但如果上下文太复杂,也有可能出错。
  1. var myFrame = document.createElement('iframe');
  2. document.body.appendChild(myFrame);
  3. var myArray = window.frames[window.frames.length-1].Array;
  4. var arr = new myArray(a,b,10); // [a,b,10]  
  5. // myArray 的构造器已经丢失,instanceof 的结果将不正常
  6. // 构造器是不能跨 frame 共享的
  7. arr instanceof Array; // false
复制代码
18、获取数组中的最大值和最小值
  1. var  numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411]; 
  2. var maxInNumbers = Math.max.apply(Math, numbers); 
  3. var minInNumbers = Math.min.apply(Math, numbers);
复制代码
19、清空数组
  1. var myArray = [12 , 222 , 1000 ];  
  2. myArray.length = 0; // myArray will be equal to [].
复制代码
20、不要直接从数组中delete或remove元素

如果对数组元素直接使用delete,其实并没有删除,只是将元素置为了undefined。数组元素删除应使用splice。

切忌:
  1. var items = [12, 548 ,'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' ,2154 , 119 ]; 
  2. items.length; // return 11 
  3. delete items[3]; // return true 
  4. items.length; // return 11 
  5. /* items 结果为 [12, 548, "a", undefined × 1, 5478, "foo", 8852, undefined × 1, "Doe", 2154, 119] */
复制代码
而应:
  1. var items = [12, 548 ,'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' ,2154 , 119 ]; 
  2. items.length; // return 11 
  3. items.splice(3,1) ; 
  4. items.length; // return 10 
  5. /* items 结果为 [12, 548, "a", 5478, "foo", 8852, undefined × 1, "Doe", 2154, 119]
复制代码
删除对象的属性时可以使用delete。

21、使用length属性截断数组

前面的例子中用length属性清空数组,同样还可用它来截断数组:
  1. var myArray = [12 , 222 , 1000 , 124 , 98 , 10 ];  
  2. myArray.length = 4; // myArray will be equal to [12 , 222 , 1000 , 124].
复制代码
与此同时,如果把length属性变大,数组的长度值变会增加,会使用undefined来作为新的元素填充。length是一个可写的属性。
  1. myArray.length = 10; // the new array length is 10 
  2. myArray[myArray.length - 1] ; // undefined
复制代码
22、在条件中使用逻辑与或
  1. var foo = 10;  
  2. foo == 10 && doSomething(); // is the same thing as if (foo == 10) doSomething(); 
  3. foo == 5 || doSomething(); // is the same thing as if (foo != 5) doSomething();
复制代码
逻辑或还可用来设置默认值,比如函数参数的默认值。
  1. function doSomething(arg1){ 
  2.     arg1 = arg1 || 10; // arg1 will have 10 as a default value if it’s not already set
  3. }
复制代码
23、使得map()函数方法对数据循环
  1. var squares = [1,2,3,4].map(function (val) {  
  2.     return val * val;  
  3. });
  4. // squares will be equal to [1, 4, 9, 16]
复制代码
24、保留指定小数位数
  1. var num =2.443242342;
  2. num = num.toFixed(4);  // num will be equal to 2.4432
复制代码
注意,toFixec()返回的是字符串,不是数字。

25、浮点计算的问题
  1. 0.1 + 0.2 === 0.3 // is false 
  2. 9007199254740992 + 1 // is equal to 9007199254740992
  3. 9007199254740992 + 2 // is equal to 9007199254740994
复制代码
为什么呢?因为0.1+0.2等于0.30000000000000004。JavaScript的数字都遵循IEEE 754标准构建,在内部都是64位浮点小数表示,具体可以参见JavaScript中的数字是如何编码的.

可以通过使用toFixed()和toPrecision()来解决这个问题。

26、通过for-in循环检查对象的属性

下面这样的用法,可以防止迭代的时候进入到对象的原型属性中。
  1. for (var name in object) {  
  2.     if (object.hasOwnProperty(name)) { 
  3.         // do something with name
  4.     }  
  5. }
复制代码
27、逗号操作符
  1. var a = 0; 
  2. var b = ( a++, 99 ); 
  3. console.log(a);  // a will be equal to 1 
  4. console.log(b);  // b is equal to 99
复制代码
28、临时存储用于计算和查询的变量

在jQuery选择器中,可以临时存储整个DOM元素。
  1. var navright = document.querySelector('#right'); 
  2. var navleft = document.querySelector('#left'); 
  3. var navup = document.querySelector('#up'); 
  4. var navdown = document.querySelector('#down');
复制代码
29、提前检查传入isFinite()的参数
  1. isFinite(0/0) ; // false
  2. isFinite("foo"); // false
  3. isFinite("10"); // true
  4. isFinite(10);   // true
  5. isFinite(undefined);  // false
  6. isFinite();   // false
  7. isFinite(null);  // true,这点当特别注意
复制代码
30、避免在数组中使用负数做索引
var numbersArray = [1,2,3,4,5];
var from = numbersArray.indexOf("foo") ; // from is equal to -1
numbersArray.splice(from,2); // will return [5]
注意传给splice的索引参数不要是负数,当是负数时,会从数组结尾处删除元素。

31、用JSON来序列化与反序列化
  1. var person = {name :'Saad', age : 26, department : {ID : 15, name : "R&D"} };
  2. var stringFromPerson = JSON.stringify(person);
  3. /* stringFromPerson 结果为 "{"name":"Saad","age":26,"department":{"ID":15,"name":"R&D"}}"   */
  4. var personFromString = JSON.parse(stringFromPerson);
  5. /* personFromString 的值与 person 对象相同  */
复制代码
32、不要使用eval()或者函数构造器

eval()和函数构造器(Function consturctor)的开销较大,每次调用,JavaScript引擎都要将源代码转换为可执行的代码。
  1. var func1 = new Function(functionCode);
  2. var func2 = eval(functionCode);
复制代码
33、避免使用with()

使用with()可以把变量加入到全局作用域中,因此,如果有其它的同名变量,一来容易混淆,二来值也会被覆盖。

34、不要对数组使用for-in

避免:
  1. var sum = 0;  
  2. for (var i in arrayNumbers) {  
  3.     sum += arrayNumbers[i];  
  4. }
复制代码
而是:
  1. var sum = 0;  
  2. for (var i = 0, len = arrayNumbers.length; i < len; i++) {  
  3.     sum += arrayNumbers[i];  
  4. }
复制代码
另外一个好处是,i和len两个变量是在for循环的第一个声明中,二者只会初始化一次,这要比下面这种写法快:
  1. for (var i = 0; i < arrayNumbers.length; i++)
复制代码
35、传给setInterval()和setTimeout()时使用函数而不是字符串

如果传给setTimeout()和setInterval()一个字符串,他们将会用类似于eval方式进行转换,这肯定会要慢些,因此不要使用:
  1. setInterval('doSomethingPeriodically()', 1000);  
  2. setTimeout('doSomethingAfterFiveSeconds()', 5000);
复制代码
而是用:
  1. setInterval(doSomethingPeriodically, 1000);  
  2. setTimeout(doSomethingAfterFiveSeconds, 5000);
复制代码
36、使用switch/case代替一大叠的if/else

当判断有超过两个分支的时候使用switch/case要更快一些,而且也更优雅,更利于代码的组织,当然,如果有超过10个分支,就不要使用switch/case了。

37、在switch/case中使用数字区间

其实,switch/case中的case条件,还可以这样写:
  1. function getCategory(age) {  
  2.     var category = "";  
  3.     switch (true) {  
  4.         case isNaN(age):  
  5.             category = "not an age";  
  6.             break;  
  7.         case (age >= 50):  
  8.             category = "Old";  
  9.             break;  
  10.         case (age <= 20):  
  11.             category = "Baby";  
  12.             break;  
  13.         default:  
  14.             category = "Young";  
  15.             break;  
  16.     };  
  17.     return category;  
  18. }  
  19. getCategory(5);  // 将返回 "Baby"
复制代码
38、使用对象作为对象的原型

下面这样,便可以给定对象作为参数,来创建以此为原型的新对象:
  1. function clone(object) {  
  2.     function OneShotConstructor(){}; 
  3.     OneShotConstructor.prototype = object;  
  4.     return new OneShotConstructor(); 

  5. clone(Array).prototype ;  // []
复制代码
39、HTML字段转换函数
  1. function escapeHTML(text) {  
  2.     var replacements= {"<": "<", ">": ">","&": "&", "\"": """};                      
  3.     return text.replace(/[<>&"]/g, function(character) {  
  4.         return replacements[character];  
  5.     }); 
  6. }
复制代码
40、不要在循环内部使用try-catch-finally

try-catch-finally中catch部分在执行时会将异常赋给一个变量,这个变量会被构建成一个运行时作用域内的新的变量。

切忌:
  1. var object = ['foo', 'bar'], i;  
  2. for (i = 0, len = object.length; i <len; i++) {  
  3.     try {  
  4.         // do something that throws an exception 
  5.     }  
  6.     catch (e) {   
  7.         // handle exception  
  8.     } 
  9. }
复制代码
而应该:
  1. var object = ['foo', 'bar'], i;  
  2. try { 
  3.     for (i = 0, len = object.length; i <len; i++) {  
  4.         // do something that throws an exception 
  5.     } 

  6. catch (e) {   
  7.     // handle exception  
  8. }
复制代码
41、使用XMLHttpRequests时注意设置超时

XMLHttpRequests在执行时,当长时间没有响应(如出现网络问题等)时,应该中止掉连接,可以通过setTimeout()来完成这个工作:
  1. var xhr = new XMLHttpRequest (); 
  2. xhr.onreadystatechange = function () {  
  3.     if (this.readyState == 4) {  
  4.         clearTimeout(timeout);  
  5.         // do something with response data 
  6.     }  
  7. }  
  8. var timeout = setTimeout( function () {  
  9.     xhr.abort(); // call error callback  
  10. }, 60*1000 /* timeout after a minute */ ); 
  11. xhr.open('GET', url, true);  
  12. xhr.send();
复制代码
同时需要注意的是,不要同时发起多个XMLHttpRequests请求。

42、处理WebSocket的超时

通常情况下,WebSocket连接创建后,如果30秒内没有任何活动,服务器端会对连接进行超时处理,防火墙也可以对单位周期没有活动的连接进行超时处理。

为了防止这种情况的发生,可以每隔一定时间,往服务器发送一条空的消息。可以通过下面这两个函数来实现这个需求,一个用于使连接保持活动状态,另一个专门用于结束这个状态。
  1. var timerID = 0; 
  2. function keepAlive() { 
  3.     var timeout = 15000;  
  4.     if (webSocket.readyState == webSocket.OPEN) {  
  5.         webSocket.send('');  
  6.     }  
  7.     timerId = setTimeout(keepAlive, timeout);  
  8. }  
  9. function cancelKeepAlive() {  
  10.     if (timerId) {  
  11.         cancelTimeout(timerId);  
  12.     }  
  13. }
复制代码
keepAlive()函数可以放在WebSocket连接的onOpen()方法的最后面,cancelKeepAlive()放在onClose()方法的最末尾。

43、时间注意原始操作符比函数调用快,使用VanillaJS

比如,一般不要这样:
  1. var min = Math.min(a,b); 
  2. A.push(v);
复制代码
可以这样来代替:
  1. var min = a < b ? a : b; 
  2. A[A.length] = v;
复制代码
44、开发时注意代码结构,上线前检查并压缩JavaScript代码

别忘了在写代码时使用一个代码美化工具。使用JSLint(一个语法检查工具)并且在上线前压缩代码(比如使用JSMin)。注:现在代码压缩一般推荐 UglifyJS (https://github.com/mishoo/UglifyJS2)

45、JavaScript博大精深,这里有些不错的学习资源

Code Academy资源:http://www.codecademy.com/tracks/javascript
Marjin Haverbekex编写的Eloquent JavaScript:http://eloquentjavascript.net/
John Resig编写的Advanced JavaScript:http://ejohn.org/apps/learn/



补充:


首先强调犀牛书很牛逼,到底有多牛逼呢,很多面试笔试的问题,其实犀牛书中都有涉及,部分问题有详解.俺很无聊的把知识测试部分给扣下来了(2章到14章),有需要的同学可以看看啦,手打难免出错,大家多多纠正.鞠躬!
chapter2
1.在下列的变量名中,哪些是合法的变量名?哪些是非法变量名?为什么
$someVariable
_someVariable
1Variable
some_Variable
function 
some*variable
----答案----
合法:
$someVariable
_someVariable
some_Variable
非法:
1Variable 首字母是非法字母
function  保留字
some*variable  包含非法字符*

2.将下列标示符转为骆驼拼写法
var some_month;
function theMonth  //返回当前月份的函数
current-month  //常量
var summer_month;//夏季月份的数组
MyLibrary-afunction//javascript包中的某个函数
----答案----
var someMonth;
function getCurrentMonth 
CURRENT_MONTH 
summerMonths
myLibraryFunction

3.下列字符串是否合法?如果不合法,如何修改?
var someString='who once said,"only two things are infinite,the universe
and human stupidity,and I'm not sure about the former."'
----答案----
字符串非法,修改方法为在双引号中只是用单引号或者转义双引号

var someString="who once said,'only two things are infinite,the universe
and human stupidity,and I'm not sure about the former.'"

var someString='who once said,"only two things are infinite,the universe
and human stupidity,and I\'m not sure about the former."'

4.对于给定的数字432.54,用什么javascript函数可以返回该数字的整数部分?如何
转换为八进制和十进制?
----答案----
var fltNumber=432.54;
var intNumber=parseInt(fltNumber);
var octNumber=intNumber.toString(8);
var hexNumber=intNumber.toString(16);

5.在JavaScript程序库中创建一个新的JavaScript函数,该函数包含一个名为someMonth
的参数,如何判断该参数是否为null或者undefined变量?
----答案----
使用以下代码测试变量是否赋值(非空并且已经定义)
if(a){...}
然而如果从来没有声明过该值,该测试会导致一个错误,因为确实向该函数传递了不存在的变量。
为避免这种错误的方式而应该把该值传递给函数之前测试该值,使用下面的代码:
if(typeof(a)!="undefined"){...}
结合测试null的代码,可以测试一个变量是否存在,是否已经定义,是否实际上有一个非空的null值
if((typeof(a)!="undefined")&&a){...}
===========================================================

chapter3
1.请为下列的表达式添加圆括号,从而使得表达式的结果为8
var valA=37;
var valB=3;
var valC=18;
var resultOfComp=varA-varB%3/2*4+varC-3;
----答案----
var resultOfComp=(varA-varB)%3/2*(4+varC)-3;

2.请使用switch语句,判断表达式的数值是否为'one','two'或者'three',当表达式为'one'或者'two'
的时候将变量的值设置为'OK';当表达式的值为'three'的时候,将变量值设置为'OK2';如果没有匹配的
值,就将变量的值设置为'NONE'。
----答案----
switch(val){
case'one':
case'two':
        result='OK';
        break;
case'three':
        result='OK2';
        break;
default:
        result='NONE';
}

3.假设有3个变量,varOne,varTwo,varThree。那么如何对这三个变量进行判断,从而仅当
varOne为33,varTwo小于等于100,但是varThree大于0的时候执行某段代码?
----答案----
if((varOne==33)&&(varTwo<=100)&&(varThree>0))

4.如果希望执行某段代码6次,有哪3种方式?对这3种方式如何取舍?
----答案----
for(var i=0;i<6;i++){...}

i=0;
while(i<6){... i++;}

i=0;
do{i++;...}while(i<6)
do...while适合不论条件是否成立都至少要执行一次代码块的情况。
for循环适合代码块需要执行特定的次数的情况。
while循适合代码块会影响条件表达式的判断的情况。

5.下列条件表达式是否有问题?如果有,那么是什么问题?
if(valTest1==valTest2)...
----答案----
如果不确定变量的数据类型,那么请考虑使用严格相等运算符
===========================================================

chapter4
1.以逗号分隔的字符串是常见的数据格式。如何根据逗号分隔的字符串创建数组呢?
请以下面的字符串创建一个数组,并访问第三个元素:
"cats,dogs,birds,horses"
----答案----
使用String.split方法,传入逗号作为分隔符,如
var animalString="cats,dogs,birds,horses";
var animalArray=String.split(animalString,",");
alert(animalArray[2]);

2.特殊字符\b是表示分隔单词的符号,而\B则是表示非分割单词符号。请定义一个正则表达式,
在下面的字符串中查找所有单词fun,并将其替换成power。
"The fun of function is that they are functional."
----答案----
var funPattern=/\bfun\b/;
var strToSearch="The fun of function is that they are functional.";
var afterMatch=strToSearch.replace(funPattern,"power");

3.编写一段代码,获取今天的日期并计算下一周同一天的日期。
----答案----
var dtNow=new Date();
var hours=dtNow.getHours();
hours+=168;//7*24
dtNow.setHours(hours);
document.writeln(dtNow.toString());

4.编写一段代码,分别对数字34.44执行向上和向下取整操作。
----答案----
var baseNum=34.44;
var numFloor=Math.floor(baseNum);//Math.floor可以对数字执行向下取整
var numCeil=Math.ceil(baseNum);//Math.ceil可以对数字执行向上取整

5.根据下面的字符串,利用模式匹配将已有的标点符号替换成逗号,然后作为数组载入,
并输出每个数值:
var str="apple.orange-strawberry,lemon-.lime";
----答案----
var strToAlter="apple.orange-strawberry,lemon-.lime";
var puncPattern=/[\.|-]/g;
var afterMatch=strToAlter.replace(puncPattern,",");
var fruits=afterMatch.split(',');
for(var i=0;i<fruits.length;i++){
        document.writeln(fruits);
        }
===========================================================

chapter5
1.对一个数字(n)执行阶乘操作,将得到1~n的数字乘积,通常写做3!(1*2*3或者6)。
或者编写一个javascript函数,使用递归的方法计算出指定数字的阶乘。
----答案----
function findFactorial(n){
if(n==0)return 1;
return (n*findFactorial(n-1));
}
var num=findFactorial(4);//将返回24

2.函数如何才能修改其作用域之外的变量?编写一个函数,由1~5的数字组成的数组作为
参数,调用该函数后把其中的数字项替换成相应的字符串表示形式(也就是"one","two"等)
----答案----
如果将一个对象(如一个数组)作为函数的参数传入,那么在函数中对这个数组的修改就会
反映到函数外部。针对这个问题,其中一种解决办法是:
function makeArray(){
var arr=[1,5,3];
alert(arr);
alterArray(arr);
alert(arr);
}

function alterArray(arrofNumbers){
for(var i=0;i<arrofNumbers.length;i++){
   switch(arrofNumbers){
        case 1:arrofNumbers="one";break;
        case 2:arrofNumbers="two";break;
        case 3:arrofNumbers="three";break;
        case 4:arrofNumbers="four";break;
        case 5:arrofNumbers="five";break;
}}}

3.创建一个函数,它的参数是一个数据对象和一个函数,它将对这个数据对象调用该函数。
----答案----
使用匿名函数满足需求
function invokeFunction(dataObject,functionToCall){
functionToCall(dataObject);
}
var funcCall=new Function('x','alert(x)');
invokeFunction('hello',funcCall);
===========================================================

chapter6
1.编写一段代码,用来测试某个变量的值,不得使用特定于浏览器的调试器。
----答案----
要测试一个变量的值最快的方法是使用警告窗口
//测试一些变量
alert(firstname);//其值要么已设置,要么为null,要么为undefined

2.css属性text-shadow的历史很有趣,它曾经被添加到CSS2标准中,但没有浏览器实现它,
然后再CSS2.1标准中又被删掉了。不过,然后浏览器实现了它,现在它已经添加到了CSS3
标准中,目前4个目标浏览器中已经有3个实现了该属性。是否可以通过对象检测来测试浏
览器是否支持这个样式属性?编写一段跨浏览器兼容的代码,对一个已有的header元素设
置这个CSS属性
----答案----
首先想到的方法可能是测试是否在style对象中实现了textShadow,这是针对该CSS属性
启用脚本的名称,但其和opacity/alpha示例一样,这不是始终可以依赖的办法。
最简单的方法是直接设置textShadow的值,不管浏览器是否支持,如果浏览器支持它,
则会改变该元素的textShadow值;如果浏览器不支持,那么仍然会动态设置该值并且忽略它:
var headerElement=document.getElementById("pageHeader");
headerElement.style.textShadow="#ff0000 2px 2px 3px";
===========================================================

chapter7
1.编写一段代码,使用DOM Level 0方法为document的click事件指定一个事件处理函数。
----答案----
document.οnclick=clickMe;

2.现在,使用DOM Level 2事件处理机制为document添加click事件处理程序(不用考虑跨浏览器兼容问题)。
----答案----
document.addEventListener("click",clickMe,false);

3.如何使问题2中所写的代码能够安全的运行在所有浏览器上?
----答案----
if(document.addEventListener){
        document.addEventListener("click",clickMe,false);
}else if(document.attachEvent){
        document.attachEvent("onclick",clickMe);
}

4.对于为document对象指定的onclick事件处理程序,如何知道是在屏幕的什么位置执行了单击操作?
----答案----
如果使用DOM Level 0的事件处理系统,那么要么访问window对象的event对象,要么将其作为
参数传递给函数。对于DOM Level 2事件处理模型而言,event对象始终会传递给事件处理函数。
可以通过event对象访问其screenX和screenY属性。

5.使用DOM Level 2事件系统,如何组织从其他元素中冒泡上来的事件?
----答案----
IE支持的方法和绝大多数浏览器支持的方法不太一样,因此需要分别支持IE和其他浏览器,
可以检查event对象是否支持stopPropagation方法,如果支持,则调用它,否则就将cancelBubble
属性设置为true.

6.将下面这段针对DOM Level 0的事件处理程序改为能够跨浏览器兼容的DOM Level 2方法:
<body>
----答案----
if(window.addEventListner){
        window.addEventListener("load",functioncall,false);
}else if(window.attachEvent){
        window.attachEvent("onload",functioncall);
}

7.编写一段JavaScript程序代码,捕获document对象的keydown事件,然后通过调用
document.writeln函数输出当前所按的键。
----答案----
虽然没有介绍过键盘捕捉事件,但在此处捕获的是keydown事件;然后从该事件的
which属性中就能够获取当前的unicode格式的键码
window.οnlοad=function(){
        if(document.addEventListener){
          document.addEventListener("keydown",getKey,false);
        }else if(document.attachEvent){
          document.attachEvent("keydown",getKey);
        }
}
function getKey(event){
  var  theEvent=event?evnt:window.event;
  document.writeln(theEvent.which);
}

===========================================================

chapter8
1.如果表单数据不完整或者无效,如何停止表单提交操作?
----答案----
如果使用DOM Level 0的事件,那么只要从事件处理程序中返回false值,并且事件处理脚本
取消对表单的提交操作即可。如果使用DOM Level 2的事件,那么就将event对象的cancelBubble
属性设置为true(针对IE),并调用其preventDefault方法(针对其他浏览器)。

2.想在表单提交之前对文本框的内容进行验证,那么应该捕获它的什么事件?
----答案----
当一个字段失去焦点时将触发blur事件,这时是检查文本框的值并确保其为有效数据的最佳时机。

3.如果要确保一个字段的内容只包含字符和空格,应该使用什么样的代码?
----答案----
var fieldPattern=/^[A-Za-z\s]*$/g;
var OK=fieldPattern.exec(document.form[0].text1.value);

4.编写一段JavaScript代码当选中一个单选按钮时捕获触发事件,如果单击其中一个按钮,
则禁用文本框;如果单击另一个按钮,则启用文本框。
----答案----
首先,代码必须为每个单选按钮的onclick事件处理程序指定一个事件处理函数:
document.forms[0].radiogroup[0].οnclick=handleClick;
document.forms[0].radiogroup[1].οnclick=handleClick;
如果有多个按钮,那么通过一个for循环实现该过程更加简单。在handleClick函数中,检查单选
按钮是否选中,并根据其结果决定是否禁用该表单元素。例如,禁用submit按钮:
function  handleClick(){
if(document.forms[0].radiogroup[1].checked){
        document.forms[0].submit.disabled=true;
}else{
        document.forms[0].submit.disabled=false;
}
}
===========================================================

chapter9
1.如果希望得到一个文本响应,那么应该使用哪种对话框?在程序代码中使用这个对话框,让用户
输入其姓氏。
----答案----
如果希望获得一个文本响应应该使用prompt对话框,
var firstname=prompt("enter your first name","");

2.定义一个定时器,使其隔3000毫秒调用一个callFunction函数,并且传入两个参数:paramA和paramB。
----答案----
setTimeout(callFunction,3000,paramA,paramB);

3.如果要检查cookie是否启用,应该使用什么样的程序代码?
----答案----
可以通过navigator对象来检查cookie是否启用:
if(navigator.cookieEnabled)...

4.创建一个大小为200px*200px的,不带工具栏和状态栏的新窗口,并在该窗口中打开Google的搜索页面。
----答案----
var newWindow=
window.open("http://www.google.com","","width=200,height=200,toolbar=no,status=no");

5.访问web页面的表单元素有哪些方法?
----答案----
如果这个表单元素有标识符,可以使用document.getElementById方法,还可以
通过document对象的forms集合来访问表单元素。
===========================================================

chapter10
1.说出几种在客户端计算机上存储信息的方法。
----答案----
将日期或者其他信息存储到客户端计算机上有以下的几种办法:
使用cookie;使用第三方插件,如flash或Google Gears;
要求用户在一个链接的资源上单击鼠标右键,然后将其保存到本地计算机上;
插入一个作为链接的可下载文件;
创建一个用来保存数据的浏览器扩展;
使用HTML5.0中的localStorage。

2.脚本的cookie由几个部分组成?
----答案----
脚本的cookie是由cookie名称,值,日期,与cookie相关联的路径组成的。

3.如何创建在浏览器关闭时自动删除的cookie?
----答案----
不提供任何有效日期,并且/或者将值设置为空。

4.对于用户输入的哪类数据需要进行清理?
----答案----
任何可以在浏览器上调用的数据,或者能够用来监听客户端cookie的,或者能够
运行服务器端进程的,在用户输入过程中都将进行清理。特别是"javascript:"
或脚本标签都会从输入中清理。但对输入清理并不完全是直接删除。对于管理工具而言,
用户在一个特定的帖子或者页面中输入脚本是可行的。但在一个多用户环境中,某个用户
就可能通过脚本获得使用该系统的其他用户信息。

5.考虑你已经创建或未来将创建的网站。请构思脚本cookie在你网站中可能实现的5个不同用途。
那么在这些应用场景中,你需要的空间是否比cookie所能提供的更大?
----答案----
维护某个人的名字,URL和评论系统的电子邮件;
为数据项提供实时反馈;
启用拼写检查;
保存登陆信息;
维护购物车;
以上这些数据所需的存储空间不超过4KB。
===========================================================

chapter11
1.所有HTML元素都支持的属性有哪些?
----答案----
这样的属性包括id,title,lang,dir,className

2.当给定一个已命名的元素时,如何使用HTML DOM找到其元素类型?
----答案----
访问该元素的tagName属性。

3.给定一个位于核心DOM中的节点,如何输出其每个子节点的元素类型?
----答案----
var children=targetNode.childNodes;
for(var i=0;i<children.length;i++){
        alert(children.nodeType);
}

4.已知页面中的所有div元素,如何找出这些div元素的ID(标识符)?
----答案----
var divs=document.getElementByTagName('div');
for(var i=0;i<divs.length;i++){
alert(divs.id);
}

5.对于下面这个元素,如果要访问它有哪三种不同类型的方法?
<div id="elem1" class="thediv">...</div>
----答案----
var theDiv=docuemnt.getElementById("elem1");

var theDivs=document.getElementByTagName("div");
var theDiv=theDivs[0];


var theDivs=document.getElementByClassName("thediv");
var theDiv=theDivs[0];

6.除了使用innerHTML,如何将下面这个div元素中的header元素换成一个段落:
<div id="elem1">
<h1>this is a header</h1>
</div>
----答案----
var targetElement=document.getElementById('elem1');
var specChild=targetElement.getElementByTagName('h1')[0];
var newPara=document.createElement('p');
var paraTxt=document.createTextNode('hello');
newPara.appendChild(paraTxt);

targetElement.replaceChild(newPara,specChild);
===========================================================

chapter12
1.当在JavaScript程序中尝试使用obj.style.color方法访问一个元素的文本颜色时,却没有任何返回值。
你知道这个字体颜色是通过样式表设置的。为什么没有任何返回值?要如何修改程序才能够获取该值?
写一段代码,访问名为“name”的元素的字体颜色,以演示你的方法。
----答案----
可以使用getComputedStyle方法或currentStyle方法,这取决于使用的是哪种浏览器。另外一种方法是在
页面载入时设置style属性。
var nameDiv=document.getElementById("name");
var nameColor;
if(nameDiv.currentStyle){
nameColor=nameDiv.currentStyle['color'];        
}else if(window.getComputedStyle){
nameColor=
document.defaultView.getComputedStyle(nameDiv,null).getPropotypeVaule('color');
}

2.对于div中的文本,如何将其显示的样式改成14px的字体,红色,行高16px?
----答案----
divElement.style.font="14px/16px";
divElement.style.color="#ff0000";

3.如果之前的修改未生效,可能是什么原因导致的?
----答案----
如果这个div元素中的文本实际上是属于另一个元素的,如一个段落元素,并且它有不同的样式设置,
那么段落元素的样式设置将覆盖外层的div元素的新样式设置。

4.让一个HTML元素块消失有哪三种办法?写一段代码,将名为“name”的元素彻底从页面布局中删除掉,
以演示方法。
----答案----
要让一个div元素消失,可以将其width或height属性设置为0,或者将整个元素完全修剪掉。还可以将
该元素的visibility属性设置为hidden,或者将其display属性设置为none。最后还可以将该元素移到
页面外,移动到最顶部或者最左边。如果要从页面布局中删除该元素,需要修改display属性:
var nameDiv=document.getElementById("name");
name.style.display="none";

5.如果拖放技术不是有效的购物车技术,那么对于这种类型的服务,可以使用哪种动态web页面效果?
----答案----
除了使用拖放功能,还可以为显示"Buy me!"信息的链接或图像添加一个鼠标单击事件处理程序,当
触发这个单击事件处理程序时,在应用程序中添加一些代码,以便自动将所选商品添加到购物车中。
===========================================================

chapter13
1.如果要为Number对象创建一个名为triple的新办法,用来求当前Number对象的数值的3倍,而且希望
该方法能够适用于所有数字,那么要怎么实现呢?
----答案----
使用Number的prototype属性:
Number.prototype.triple=function(){
  var nmToTriple=this.valueOf()*3;
  return nmToTriple;
}
var newNum=new Number(3.0);
alert(newNum.triple());

2.如何隐藏新对象的数据成员?为什么要这样做?
----答案----
通过var关键字声明数据成员,而不是把数据成员赋予this。数据隐藏的目的是控制如何访问或者修改数据。

3.创建一个参数为数字类型的函数,并且当参数类型错误时返回错误。如果不使用return语句,应该
实现该功能?
----答案----
使用throw语句触发错误,然后在主调程序中通过try...catch语句捕捉异常。
if(typeof value !="number"){
        throw "NotANumber";
}

4.在之前的事例中可以用于事件的对象检测代码
var theEvent=nsEvent?nsEvent:window.event;
为什么在处理透明度差异的时候不能使用相同的功能呢?
----答案----
与event对象不一样,处理透明度的时候不只会涉及到业务模型上的差异。不仅属性不同,而且与
赋值属性的可能值有关。

5.创建一个自定义对象,使其拥有3个公有办法,changeState,getColor和getState;以及两个私有
数据成员:background和state。将state属性设置为on,将background颜色属性设置为#fff。
changeState方法同时用来判断state是否为on,如果state为on,那么将state改为off,并同时将
颜色设置为#000。getColor方法将返回背景颜色,getState负责返回状态。
----答案----
function Control(){
  var state='on';
  var background='#fff';
  
  this.changeState=function(){
        if(state=='on'){
          state='off';
          background='#000';
        }else {
          state='on';
          background='#fff';
        }
  };
  this.getState=function(){
     return state;
  };
  this.getColor=function(){
     return background;
  };
}
===========================================================

chapter14
1.XMLHttpRequest请求也可以设置为同步模式(也就是停下来等待响应),虽然这看起来和Ajax
的概念有些背道而驰。但应该如何打开这样的请求呢?
----答案----
XMLHttpRequest.open函数的第三个,可选的参数是一个布尔值。将该参数设置为true(默认值)
将创建异步请求;如果将其设置为false则将创建同步请求。

2.当请求接受到响应时,就需要对响应进行处理。那么如何指定在服务器响应时调用的函数呢?
----答案----
当获得XMLHttpRequest对象的引用并调用其open方法之后,将赋值给onReadyStateChange属性。

3.对于Ajax请求而言,表示请求成功需要对哪两个状态进行判断?表示请求完成呢?
----答案----
XMLHttpRequest对象的readyState属性值为4就表示请求完成,要表明服务请求是成功的,
还必须确保其status属性值为200。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值