读书人

JavaScript语言精髓-学习总结

发布时间: 2013-03-27 11:22:42 作者: rapoo

JavaScript语言精粹---学习总结

????''?==?'0';??//false

????0?==?'';????//true

????0?==?'0';???//true

???

????false?==?'false';??//false

????false?==?'0';??????//true

???

????false?==?undefined;?//false

????false?==?null;??????//false

????null?==?undefined;??//true

???

????' \t\r\n '?==?0;????//true

?

通过上面的例子,大师建议我们:永远不要使用?==?和?!=?,请始终使用?===?和?!==?,有这两个运算符的话,以上例子全部为false!

?

2、eval

eval?函数传递一个字符串给JavaScript编译器,并且执行其结果。它是一个被滥用得最多的JavaScript特性。例如:如果你知道点表示法,但不知道下标表示法,就可能会这么写:(我为了实现一个功能,专门研究了一下eval函数,最后用下面的方法写出了想要的功能,高兴得很!当第二天看到这位大师这么说的时候,想死的心都有了!哎!)

????eval("myValue = myObject."+?myKey?+";");

而不是这么写:

????myValue = myObject[myKey];

使用eval形式的代码会更加难以阅读。而且也会降低语言的性能。

所以,大师建议我们:eval、Function、setTimeout、setInterval?这四个方法应该避免使用!

我决定了,以后都不用了,呵呵!

?

3、++ --

作为一条原则,大师建议我们:不再使用这两个运算符,用?+=?和?-=?代替!

?

4、function?语句对比函数表达式

下面的语句:

????function foo(){}

意思相当于:

????var foo = function (){};

大师建议我们:用第二种形式!

?

5、类型的包装对象

JavaScript?有一套类型的包装对象。例如

???????new Boolean(false)

会返回一个对象,该对象有一个valueOf方法会返回被包装的值。这其实完全没有必要,并且有时还令人困惑。

大师建议我们:不要使用new Boolean?、?new Number?或?new String,同时避免使用?new Object?和?new Array。可使用{}和[]来代替!

?

6、new

new这个东西说了很多,也很有用(个人感觉),可是大师建议我们:一个更好的应对策略就是根本不去使用?new?。

?

7、JavaScript的假值

?

这些值全部等同于假,但它们?是不可互换的。例如,这是用一种错误的方式去确定一个对象是否缺少一个成员元素:

????value = myObject[name];

???????if (value == null) {

?????????alert(name + ' not found. ');

????}

undefined?是缺失的成员元素的值,但该代码片段用null?来测试。它使用了会强制类型转换的==运算符,而不是更可靠的===运算符。

?

8、NaN

NaN是一个特殊的数量值,它表示不是一个数字,可是他的类型却是number?,可以通过下面的代码来验证:

????typeOf NaN === 'number'??// true

????NaN === NaN???????????//false

????NaN !== NaN????????????//true

?

????isNaN (NaN)?????????????//true

????isNaN (0)????????????????//false

????isNaN('oops')?????????????//true

????isNaN('0')????????????????//false

?

大师列出了上面几条,最后建议我们:自己写一个判断是不是数字的方法!

????????var isNumber = function(value){

??????????????return typeof value === 'number' && isFinite(value);

????????};

?

9、parseInt

????/**

?????*?parseInt?是一个将字符串转换为整数的函数,

?????*?它在遇到非数字时停止解析,

?????*?以致于出现下面的情况。

?????*/

????var?myValue1?=?parseInt("16");???????????????//myValue1 = 16

????var?myValue2?=?parseInt("16 is a number");???//myValue2 = 16

???

????/**

?????*?如果一个字符串是以0开头的,

?????*?那么该字符串将被基于八进制而不是十进制来求值。

?????*?在八进制中,8和9不是数字,所以会出现下面错误。

?????*/

????var?myValue3?=?parseInt("08");?//myValue3 = 0

????var?myValue4?=?parseInt("09");?//myValue4 = 0

???

????/**

?????*?这个错误导致了程序解析日期和时间时出现问题。

?????*?幸运的是,parseInt可以接受一个基数作为参数,

?????*?我们可以用下面的方法去代替

?????*/

????var?myValue5?=?parseInt("08",?10);?//myValue5 = 8

?

10、编码风格

大师建议我们:{}的{?一定要放到一行的结束,不要放到一行的开始!

?

二:对象

1、对象字面量(对象的定义)

????/**

?????*?1、对象是属性的容器。

?????*?2、“名/值”对?"first-name"/"Jerome"。

?????*?3、属性名只要是符合合法的命名且不是保留字,可以不用“”号括住,

?????*????所以"first-name"必需括住,因为“-”不是合法的命名,

?????*????而first_name,则不必括住。

?????*?4、属性之间用“,”号分隔。

?????*?5、对象可以嵌套。

?????*/

????var?empty_object?=?{};

???

????var?stooge?=?{

????????"first-name":?"Jerome",

????????"last-name":?"Howard"

????};

???

????var?flight?=?{

????????airline:?"Oceanic",

????????number:?815,

????????departure:?{

????????????IATA:?"SYD",

????????????time:?"2009-09-09 14:55",

????????????city:?"Sydney"

????????},

????????arrival:?{

????????????IATA:?"LAX",

????????????time:?"2009-09-09 14:55",

????????????city:?"Los Angeles"

????????}

????};

?

2、检索(对象属性访问)

????/**

?????*?要检索对象中的值,可以用[]和.两种方式,

?????*?但是要注意,属性名要符合规则且不是保留字的时候才能用.的方式访问

?????*/

????var?strValue1?=?stooge["first-name"];??//strValue1 = Jerome,这样是对的

????var?strValue2?=?stooge.first-name;?????//这样是错误的

????var?strValue3?=?stooge["last_name"];???//strValue3 = Howard,这样是对的

????var?strValue4?=?stooge.last_name;??????//strValue4 = Howard,这样是对的

???

????/**

?????*?如果你尝试检索一个不存在的成员元素的时候,将返回一个undefined值

?????*/

????stooge["middle-name"]??//undefined

????flight.status??????????//undefined

????stooge["FIRST-NAME"]???//undefined

???

????/**

?????*??||?运算符可以用来填充默认值

?????*/

????var?middle?=?stooge["middle-name"]?||?"asdf";

????var?status?=?flight.status?||?"unknown";

???

????/**

?????*对象通过引用来传递,它们永远不会被拷贝

?????*/

????var?x?=?stooge;

????x.nickname?=?'Curly';

????var?nick?=?stooge.nickname;??//nick = Curly

?

三:函数

1、函数字面量(函数定义)

var?add?=?function?(a,?b){

????return?a?+?b;

};

?

2、调用

函数除了声明时定义的形式参数,还有两参数this?和?arguments。

函数的调用有四种:方法调用模式、函数调用模式、构造器调用模式、apply?调用模式,这些模式在如何初始化关键参数this上存在差异。

?

方法调用模式

当一个函数保存为对象的一个属性时,我们称它为一个方法。

//创建?myObject,它有一个value属性和一个increment方法。

//increment方法接受一个可进的参数,如果不是数字,那么默认使用数字1

//this被绑定到myObject

var?myObject?=?{

????value:?0,

????increment:?function(inc){

????????this.value?+=?typeof?inc?===?'number'???inc?:?1;

????}

};

?

myObject.increment();

document.writeln(myObject.value);?//1

?

myObject.increment(2);

document.writeln(myObject.value);?//3

?

函数调用模式

当一个函数并非一个对象的属性时,那么它被当作一个函数来调用。

// sum的值为7,add函数在这里被调用是函数调用模式

// this被绑定到全局对象

var?sum?=?add(3,?4);

?

?

构造器调用模式

/**

?*?在调用函数的时候,前面加上一个new来调用,称为构造器调用

?*?this被绑定到新函数

?*?注意:大师建议不使用这种方式的构造器函数

?*/

//创建一个名为Quo的构造器函数,它构造一个带有status属性的对象

var?Quo?=?function(string){

????this.status?=?string;

};

?

//给Quo的所有实例提供一个名为get_status的公共方法

Quo.prototype.get_status?=?function(){

????return?this.status;

};

?

//构造一个Quo实例

var?myQuo?=?new?Quo("confused");

?

apply调用(看不懂,不记录了)

?

?

3、异常

var?add?=?function(a,?b){

????if(typeof?a?!==?'number'?||?typeof?b?!==?'number'){

????????throw?{

????????????name:?'TypeError',

????????????message:?'add needs numbers'

????????};

????}

};

?

var?try_it?=?function(){

????try{

????????add("seven");

????}catch(e){

????????document.writeln(e.name?+?':'?+?e.message);

????}

};

?

try_it();

?

4、给类型增加方法

//JavaScript给类型增加方法的时候,必须以下面这种格式

String.prototype.methodName?=?function(){

};

?

//这样做很麻烦,所以我们用一个方法解决

Function.prototype.method?=?function(methodName,?methodFunc){

????if(!this.prototype[methodName]){

????????this.prototype[methodName]?=?methodFunc;

????}

????return?this;

};

//这样我们在以后扩展方法的时候就方便多了

Number.method('integer',?function(){

????return?Math[this?<?0???'celling'?:?'floor'](this);

});

document.writeln((-10?/?3).integer());?//-3

?

//JavaScript缺少一个移除字符串末端空白的方法

String.method('trim',?function(){

????return?this.replace(/^\s+|\s+$/g,?'');

});

document.writeln(" asdf ".trim());

?

5、递归

?

?

?

?

?

?

6、闭包

一个函数可以访问它被创建时所处的上下文环境,这被称为闭包!

例:

//把一个节点的颜色由黄色渐到白色

var?face =?function(node){

??var?level = 1;

??var?step =?function(){

????var?hex = level.toString(16);

????node.style.backgroundColor =?'FFFF'?+ hex + hex;

????if(level < 15){

????????level += 1;

????????setTimeout(step, 100);

????}

??};

??setTimeout(setp, 100);

};

face(document.body);

?

一个很不好的例子:

/**

?*?可以想象一下,下面的alert会出现什么问题呢?

?*?alert只会出现1个数字,nodes.length?+?1?之后的数字,为什么呢?

?*?因为函数有访问它被创建时所处的上下文环境,这被称为闭包!i一直在变!

?*/

var?add_the_handlers =?function(nodes){

??var?i;

??for(i=0; i<nodes.length; i+=1){

????nodes.on allowScriptAccess="never" allowNetworking="internal" wmode="transparent"click =?function(){

????????alert(i);

????};

??}

};

?

/**

?*

?*/

var?add_the_handlers =?function(nodes){

????var?i;

????for(i=0; i<nodes.length; i+=1){

???????nodes.on allowScriptAccess="never" allowNetworking="internal" wmode="transparent"click =?function(){

?????????return?function(e){

???????????alert(e);

?????????}

???????}(i);

????}

};

?

7、继承

/**

?*?推荐以这种方式实现继承

?*/

if(typeof?Object.beget !==?'function'){

????Object.beget =?function(o){

???????var?F =?function(){};

???????F.prototype = o;

???????return?new?F();

????};

}

?

var?myMammal = {

????name :?'Herb the Mammal',

????get_name :?function(){

???????return?this.name;

????},

????says :?function(){

???????return?this.saying ||?'';

????}

};

?

var?myCat = Object.beget(myMammal);

myCat.name =?'Henrietta';

myCat.saying =?'meow';

myCat.purr =?function(n){

????var?i, s =?'';

????for(i = 0; i < n; i += 1){

???????if(s){

???????????s +=?'-';

???????}

???????s +=?'r';

????}

????return?s;

};

myCat.get_name =?function(){

????return?this.says +?' '?+?this.name +?' '?+?this.says;

};

?

三、数组

1、如何判断一个对像是不是数组

/**

?*?判断一个对象是不是数组

?*/

var?is_array =?function(value){

????return?value &&

???????????typeof?value ===?'object'?&&

???????????typeof?value.length ===?'number'?&&

???????????typeof?value.splice ===?'function'?&&

???????????!(value.propertyIsEnumerable('length'));

};

?

/**

?*?扩展reduce方法,

?*?接收一个计算函数和一个计算的初始值,

?*?并返回最后的计算结果

?*/

Array.method('reduce',?function(func, value){

??var?i;

??for(i=0; i<this.length; i+=1){

????value =?func(this[i], value);

??}

??return?value;

});

?

//下面是用法

?

var?data = [4, 8, 15, 16, 23, 42];

?

var?add =?function(a, b){

????return?a + b;

};

?

var?mult =?function(a, b){

????return?a * b;

};

?

var?sum = data.reduce(add, 0);?//sum = 108

var?product = data.reduce(mult, 1);?// product = 7418880

?

2、维度

JavaScript的数组通常不会初始化,如果你用[]得到一个新的数组,它将是空的。如果你访问一个不存在的元素,则将得到的值是undefined。我们可以设置一个Array.dim方法,用于创建和初始化数组。

/**

?*?创建并初始化一个数组

?*/

Array.dim =?function(dimension, initial){

????var?a = [], i;

????for(i=0; i<dimension; i+=1){

???????a[i] = initial;

????}

????return?a;

};

/**

?*?创建并初始化一个二维数组

?*/

Array.matrix =?function?(m, n, initial){

????var?a, i, j, mat = [];

????for(i=0; i<m; i+=1){

???????a = [];

???????for(j=0; j<n; j+=1){????

???????????a[j] = initial;

???????}

???????mat[i] = a;

????}

};

?

四、正则表达式

1、先确定哪些方法可以使用正则表达式

regexp.exec、regexp.test、string.match、string.replace、string.search、string.split

?

2、通过两个例子解析正则表达式

var?parse_url =?/^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;

var?url =?"http://www.ora.com:80/goodparts?q#fragment";

?

/**

?*?让我们来调用parse_url的exec方法。

?*?如果能成功地匹配我们传给它的字符串,

?*?它将会返回一个数组,该数组包含了从这个url中提取出来的片段

?*?result结果为:

?*?['http://www.ora.com:80/goodparts?q#fragment',

?*??'http',

?*??'//',

?*??'www.ora.com',

?*??'80',

?*??'goodparts',

?*??'q',

?*??'fragment'

?*?]

?*/

var?result = parse_url.exec(url);

?

/**

?*?匹配一个数字,test方法返回boolean

?*/

var?parse_number =?/^-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?$/i;

parse_number.test('1');??????//true

parse_number.test('number');?//false

parse_number.test('98.6');???//true

parse_number.test('132.21.03.10');?//false

parse_number.test('123.45E-67');???//true

parse_number.test('123.45D-67');???//false

?

?

/**

?*?解析:

?*?1、^字符表示这个字符串的开始。

?*?2、$字符表示这个字符串的结束。

?*?3、+字符表示1或多次。

?*?4、?字符表示0或1次。

?*?5、*字符表示0或多次。

?*?6、_字符表示任一字符

?*?7、[]字符表示只能对应包含的数据,[A-Za-z]表示:可以对应26个英文字母的大小写

?*?8、(?:...)字符表示一个非捕获型分组,(...)表示一个捕获型分组,

?*????说白了就是(...)括中的对应数据会放到匹配结果中,

?*????(?:...)就不会放到匹配结果中

?*?9、{m,?n}表示m-n之间次。

?*?10、|字符表示或

?*?11、.字符匹配除行结束符以外的任何字符

?*?12、\d=[0-9],\D相反。

?*?13、\s表示空白,\S相反。

?*?14、\w=[0-9A-Z_a-z],\W相反。

?*/

?

读书人网 >JavaScript

热点推荐