版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://ligang.blog.csdn.net/article/details/44701817
JavaScript是Web浏览器语言,浏览器的API和文档对象模型(DOM)相当糟糕,使得JavaScript遭到不公平的指责。
函数就是数值!
一、语法
1. 注释
JavaScript提供了【/*块注释*/】、【//行注释】两种方式,建议大家使用行注释,不要使用块注释。
/*
var rm_a = /a*/.match(s);
*/
复制
配合正则使用,会发生错误!
2. 数字
JavaScript只有一个数字类型。它在内部被表示为64位的浮点数,和Java的double数字类型一样。从而避免了短整型的溢出问题。
NaN | 是一个数值,isNaN(number)可判断是否为数字 |
---|---|
Infinity | 表示大于1.79769313JavaScript中有一个Math对象,包含了一套用于数字的方法。例如:Math.floor(number); //把数字转化为整数486...e+308的值 |
Math | JavaScript中有一个Math对象,包含了一套用于数字的方法。例如:Math.floor(number); //把数字转化为整数 |
PS:毒瘤
(1). 0.1+0.2不等于0.3
推荐:
(0.1*10 + 0.2*10)/10 = 0.3
(2). typeof NaN === 'number'; //true
NaN === NaN; //false
NaN !== NaN; //false
可辨别数字:isNaN(number)
判断是否可用做数字:isFinite(""); 其会筛选NaN和Infinity,但会试图把它的运算符串转为数字
例:isFinite("123"); //true isFinite("123A"); //false isFinite(Infinity); //false
isNaN("123") //false isNaN("123A"); //true isNaN(Infinity); //false
推荐:
var isNumber = function isNumber(value){
return typeof value === 'number' && isFinite(value);
}
复制
例:isNumber(123); //true isNumber("123"); //false
3. 字符串
JavaScript没有字符类型。要表示一个字符,只需创建仅包含一个字符的字符串即可。JavaScript在被创建的时候,Unicode是一个16为的字符集,所以JavaScript中的所有字符都是16位的。
字符串拥有一个特性,一旦被创建,永无法改变;但可通过"+"创建一个新的字符串。
var s = "hello";
s.toUpperCase();
console.log(s); // HELLO,此处的s同声明时var s不是一个对象!
复制
4. 语句
在web浏览器中,每个<script>标签提供一个被编译且立即执行的编译单元;因为缺少链接器,JavaScript把它们一起抛到一个公共的全局命名空间中。
switch、while、for和do语句允许有一个可选的前置标签(label),它配合break语句来使用。
5. 表达式
typeof运算符产生的值有:'number'、'string'、'boolean'、'undefined'、'function'、'object',其中数组和null也会返回object。
二、对象
JavaScript的简单数据类型包括数字、字符串、布尔值、null和undefined;其他所有的都是对象。
1. 对象字面量:包围在一对花括号中的零或多个“名/值”对
var a = {};
var b = {"first-name":"lee",
"last-name":"gang"};
复制
其中,属性名不强制要求用引号括住
2. 检索
JavaScript中有两种检索方式:[]和.
小技巧;
(1). 使用"||"运算符来填充默认值
var status = flight['status'] || "unkown";
复制
对于上述flight['status'],不存在成员属性值返回undefined
(2). 尝试从undefined的成员属性取值,会导致TypeError异常,可通过"&&"运算符避免错误:
if(flight && flight.status){
var status = flight['status'] || "unkown";
}
复制
3. 引用
对象通过引用来传递。它们永远不会被复制;
var x = stooge;
x.nickname = 'leegang';
var nick = stooge.nickname; //因为x和stooge是指向同一个对象的引用,所有nick为'leegang'
复制
4. 原型
每个对象都连接到一个原型对象,并且它可以从中继承属性。所有通过对象字面量创建的对象都连接到Object.prototype,它是JavaScript中的标配对象。
当创建一个对象时,可以选择某个对象作为它的原型。
对某对象做出改变时,不会触及对象的原型,只有在检索值的时候才被用到【委托】。
属性值自身找不到 --> 原型 --> ... --> Object.prototype
原型关系是一种动态关系,添加一个新属性到原型中立即对所有基于该原型创建的对象可见。
5. for-in
可枚举出所有的属性,包括函数和原型中的属性。
过滤非值:typeof props['name'] !== 'function'
过滤非自身:hasOwnProperty()
var obj = {a:'123',b:'456',c:function(){return 1}};
/* 获得对象的属性个数*/
function count(obj){
var length = 0;
var type = typeof obj;
if(type === "string"){
length = obj.length;
}else{
for(var o in obj){
length++;
}
}
return length;
}
复制
6. 减少全局变量污染
只创建一个唯一全局变量,其他变量和对象都作为该变量的属性。
var myApp = {};
myApp.stooge = {};
myApp.flight = {a:'123',b:'456'};
复制
三、 函数
函数 --> Function.prototype --> Object.prototype
1. 函数字面量
var add = function(a,b){
return a+b;
};
复制
函数字面量可以出现在任何允许表达式出现的地方。函数也可以被定义在其他函数中。一个内部函数除了可以访问自己的参数和变量,同时它也能自有访问把它嵌套在其中的父函数的参数与变量。通过函数字面量创建的函数对象包含一个连到外部上下文的连接。这被称为闭包。
2. 函数调用
调用一个函数会暂停当前函数的执行,传递控制权和参数给新函数。除了声明时定义的形式参数,每个函数还接收两个附件的参数:this和arguments。
(1). 方法调用模式
当一个函数被保存为对象的一个属性时,其被称为方法。当一个方法被调用时,this被绑定到该对象。
var myObject = {
value:0,
increment:function(inc){
this.value += typeof inc === 'number' ? inc : 1;
}
};
复制
调用:对象.方法
myObject.increment();
myObject.value; // 1
myObject.increment(2);
myObject.value; // 3
(2). 函数调用模式
当一个函数并非一个对象的属性时,那么它就是被当做一个函数来调用的:
var sum = add(1,2);
此模式调用函数时,this被绑定到全局对象。
导致问题:
方法不能利用内部函数来帮助它工作,因为内部函数的this被绑定到了错误的值,所以不能共享该方法对对象的访问权。
解决方案:
如果该方法定义一个变量并给它赋值为this,那么内部函数就可以通过那个变量访问到this。
myObject.double = function(){ // 给myObject增加一个double方法
var that = this; // 解决方案,this为myObject
var helper = function(){
/* helper方法中,this指向全局, that指向myObject*/
that.value = add(that.value,that.value);
};
helper(); // 以函数形式调用helper
};
myObject.double(); // 以方法形式调用double
复制
总结如下:
obj.method = function(){ //方法
// 方法中,this被绑定到当前obj对象
that = this;
var fun = function(){ //函数
// 函数中,this被绑定到全局对象
// this.value 不可以;this.add 全局方法可以
// 将外部方法中的this另存到that中,避免被函数中this覆盖!
};
};
复制
(3). 构造器调用模式
在一个函数前面带上new来调用,那么背地里将会创建一个连接到该函数的prototype成员的新对象,同时this会被绑定到那个对象上。
/* 创建一个名为Quo,带有status属性的构造器函数*/
var Quo = function(str){
this.status = str;
};
/* 给Quo的所有实例提供一个名为get_status的公共方法*/
Qu0.prototype.get_status = function(){
return this.status;
};
var myQuo = new Que("confused");
复制
(4). Apply调用模式
apply方法构造一个参数数组传递给调用函数。其接收两个参数,第1个是要绑定给this的值,第2个是参数数组。
// 实例一:构造一个包含两个数字的数组,并将它们相加
var arr = [3,4];
var sum = add.apply(null,arr);
// 实例二:构造一个包含status成员的对象,并调用Quo上的get_status方法[非继承方式]
var statusObject = {status:'A-OK'};
var status = Quo.prototype.get_status.apply(statusObject);
复制
3. 函数返回
一个函数总会返回一个值。如果没有指定返回值,则返回undefined。
4. 异常
var add = function(a,b){
if(typeof a !== 'number' || typeof b !== 'number'){
throw{
name:'TypeError',
message:'add needs numbers'
};
}
return a+b;
}
/* throw语句中断函数的执行,它会抛出一个exception对象,该对象包含的属性可自定义*/
var try_it = function(){
try{
add("seven");
}catch(e){
document.writeln(e.name+":"+e.message);
}
}
try_it();
复制
5. 扩展类型的功能
JavaScript允许给语言的基本类型扩充功能。
Function.prototype.method = function(name,func){
this.prototype[name] = func;
return this;
};
复制
在Function原型上添加method,其所有方法上都可用method
/* 取整*/
Number.method('integer',function(){
return Math[this<0?'ceil':'floor'](this);
});
/* 移除字符串首尾空白*/
String.method('trim',function(){
return this.replace(/^\s+|\s+$/g,'');
});
复制
6. 闭包
内部函数拥有比它的外部函数更长的生命周期!!!
函数可以访问它被创建时所处的上下文环境!!!
内部函数能访问外部函数的实际变量,而无需复制!
常用解决方案:
(1)给对应的li添加一个属性记录是第几个如 id=0,1,2,3
(2)将函数外移,避免函数套函数
7. 回调
request=prepare_the_request();
response=send_request_synchronously(request);
display(response);
这种方式的问题在于网络上的同步请将会导致客户端进入假死状态。如果网络传输或服务器很慢,响应性的降低将是不可接受的。
更好的方式是发起异步的请求,提供一个当服务器的响应到达时将被调用的回调函数。这样客户端不会被阻塞。
request=prepare_the_request();
send_request_asynchronously(request,function(response){
display(response);
});
8. 模块
模块通常结合单例模式使用。JavaScript单例就是用对象字面量表示法创建的对象,对象的属性值可以是数值或函数,并且属性值在该对象的生命周期中不会发生变化。
var serial_maker = function(){
var prefix = '';
var seq = 0;
return{
set_prefix:function(p){
prefix = String(p);
},
set_seq:function(s){
seq = s;
},
gensym:function(){
var result = prefix + seq;
seq +=1;
return result;
}
};
};
var seqer = serial_maker();
seqer.set_prefix('Q');
seqer.set_seq(1000);
var unique = seqer.gensym(); // 'Q1000'
复制
模块的一般形式:一个定义了私有变量和函数的函数;利用闭包创建可以访问私有变量和函数的特权函数;最后返回这个特权函数,或者把它们保存到一个可访问到的地方。