专栏首页Super 前端JavaScript语言精粹【语法、对象、函数】

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

版权声明:本文为博主原创文章,遵循 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'

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JSON Bigint 大数精度丢失的背后

    如果你在 Chrome Dev Tools 控制台中输入 JSON.parse('{"taskid": 9007199254740993}') 运行结果返回的将...

    猫哥学前班
  • jQueryEasyUI 的入门

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>EasyUI拖动效果</title> <...

    用户5927264
  • 搭建自己的脚手架

    最近接手了一个内部配置运营平台,大概了解了代码结构之后,第一波优化就是搭建了一套脚手架。

    暂七师黑管手
  • 当你在浏览器中输入“google.com”并回车,会发生什么?

    曾经遇到过的一个最喜欢的面试问题是这样的:你键入'google. com'到一个浏览器地址栏中, 并点击<Enter>, 之后会发生什么呢?

    养码场
  • JS的常用操作

    用户在进行注册的时候会输入一些内容,但是有些用户会输入一些不合法的内容,这样 会导致服务器的压力过大,此时我们需要对用户输入的内容进行一个校验(前端校验和后台 ...

    用户5927264
  • ES6数组操作方法

    concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组,仅会返回被连接数组的一个副本。

    用户1437675
  • java小工具-使用springboot-starter启动检查配置是否满足要求

    随着项目不断的迭代,不断的有新的组件加入进来,比如现在项目中就集成了cat,apollo,prometheus,docker,k8s等等 , 随之而来的有一大堆...

    微笑的小小刀
  • promise源码详解,助力你轻松掌握promise

    在没有出来promise之前,为了拿到函数的回调结果,我们不得不使用callback function,这种代码的维护和理解是相当恶心了! 下面我们来看看这个恶...

    前端老鸟
  • canScrollHorizontally()/canScrollVertically() 无法获取到正确执行的解决方案

    使用一个 RecyclerView 实现了一个类似 Tab 效果,当这个 Tab 可以滑动时,显示最右侧的三角按钮,否则隐藏这个按钮。效果如图

    阳仔
  • JS最新基本数据类型:BigInt

    BigInt数据类型的目的是比Number数据类型支持的范围更大的整数值。在对大整数执行数学运算时,以任意精度表示整数的能力尤为重要。使用BigInt,整数溢出...

    前端小智@大迁世界

扫码关注云+社区

领取腾讯云代金券