JavaScript语言精粹【语法、对象、函数】

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的值
MathJavaScript中有一个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'

模块的一般形式:一个定义了私有变量和函数的函数;利用闭包创建可以访问私有变量和函数的特权函数;最后返回这个特权函数,或者把它们保存到一个可访问到的地方。



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋飛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值