JS第三周

173 阅读7分钟

一、正则表达式

分割、替换、验证:

目的:会看、会改、会答

1、正则表达式:

1、最简单的正则:/原文/后缀ig

2、规定一位字符可能出现的情况:备选字符集 /[0-9]/

3、预定义字符集: \d - 一位数字 \w - 一位数字、字母、下划线 \s - 一位空白字符 . - 除了换行外的任意字符

4、量词: {n,m} - 最少n次,最多m次 {n,} - 最少n次,多了不限 {n} - 只能n次

+ - 至少一次,多了不限
* - 可有可无,多了不限
? - 可有可无,最多一次

5、指定位置 ^ $ 特殊:两者同时使用,代表从头到尾完全匹配 - 验证

6、选择和分组 (规则1|规则2)

7、预判的公式: (?!\s+$)

二、字符串中支持正则的API:

var newStr=str.replace(reg,"新内容");

var newStr=str.replace(reg,function(a){
	//a:当前正则匹配到的关键字
});   

格式化:正则中带有分组 var newStr=str.replace(reg,function(a,b,c...){ //a:当前正则匹配到的关键字 //b:第一个分组获取到的内容 ... });

切割:var arr=str.split(reg);

三、创建正则对象:2种

1、直接量:var reg=/正则表达式/后缀
2、构造函数:var reg=new RegExp("正则表达式","后缀")  

方法:验证:var bool=reg.test(user);

1、Math:数学计算,不允许创建,自带

属性:Math.PI

API: 1、取整: Math.ceil(num); Math.floor(num); Math.round(num);

2、乘方:Math.pow(底数,幂);
   开方:Math.sqrt(num);

3、最大值和最小值
	Math.max/min(a,b,c,d,e...);
	支持数组:Math.max/min.apply(Math,arr);

4、绝对值:Math.abs(num);

5、随机整数:parseInt(Math.random()*(max-min+1)+min);
	

2、Date:创建日期,操作日期的API

创建:
  1、当前时间:var now=new Date();

  2、自定义时间:var date=new Date("yyyy/MM/dd hh:mm:ss");
		var date=new Date(yyyy,MM-1,dd,hh,mm,ss);

  3、复制日期:var end=new Date(start);

操作:
  1、两个日期可以相减,得到的毫秒差可以换算出你想要的分量
  2、FullYear Month Date Day Hours Minutes Seconds
	每一个分量都有一对儿getXXX/setXXX,除了Day没有set操作

	为某个分量做+-
	date.setXXX(date.getXXX+/-n);

  3、格式化:date.toLocaleString();//带有兼容性问题,最好还是自定义format方法

3、Number:

创建:var num=new Number();
   num.toFixed(d);//结果是一个字符串
   num.toString();

4、Boolean:

创建:var bool=new Boolean();

一切的引用类型的对象,都具有属性和方法:创建的底层都是一个构造函数,直接量都是后续添加上,除了Math不能创建

1、Error

1、浏览器自带 4种错误类型:

1、语法错误:SyntaxError - 符号错了
2、引用错误:ReferenceError - 没有创建
3、类型错误:TypeError - 不是你的方法你却去使用了
4、范围错误:RangeError - num.toFixed(d);//d 0-100之间

2、抛出自定义错误:

throw new Error("错误信息");

3、错误处理:希望不要报错,而是给一个错误提示,不会打断后续代码

try{
	可能出错的代码
}catch(err){
	console.log("错误提示");
}

还不如用if...else提前的预判 - 规定用户只能输入什么(!isNaN、正则、控制范围)

2、Function

创建:构造函数:var 函数名=new Function("形参1","形参2",...,"函数体;return 结果");

重载:同一个函数名,根据传入的实参的不同,执行对应的函数

      arguments类数组对象:哪怕没有形参,接住所有的实参
		arguments[0] - 第一个实参
		arguments[1] - 第二个实参
		...

	function f1(){
		if(arguments.length==1){

		}else if(arguments.length==2){

		}...
	}

匿名函数:只会使用一次就会自动释放,因为没有函数名/变量名,没有变量引用着的引用类型对象会被垃圾回收器立刻释放

1、自调:代替全局作用域

		(function(){
			开始写自己的代码 - 变量会自动释放
		})();

2、回调:多半都是API里前辈提供好的,我们学习了就可以直接使用,以后回调函数可以简化箭头函数

		只要匿名函数,不是自调,一定就是回调
		arr.sort(function(a,b){return a-b})
		elem.onclick=function(){}

1、Function的闭包:

目的:保护一个可以【反复使用的局部变量】的一种词法结构

语法:
function outer(){
	受保护的变量
	return function(){
		操作受保护的变量
	}
}

var 内层函数=outer();
使用场景:防抖节流
function outer(){
	var timer=null;
	return function(){
		if(timer){clearTimeout(timer)}
		timer=setTimeout(function(){
			操作
		},间隔毫秒数)
	}
}

var xx=outer();

elem.onmousemove/input.oninput/window.onresize=function(){
	xx();
}

2、Object面向对象三大特点:

一、封装

   1、*直接量:使用创建单个对象
	var obj={
		"属性名":属性值,
		...
		"方法名":function(){},
		...
	}

   2、预定义构造函数:
	var obj=new Object();//空对象
	追加属性和方法
	obj.属性名=属性值
	obj.方法名=function(){}

   3、自定义构造函数:创建多个对象
	1、创建构造函数
		function 构造函数名(xingming,nianling,aihao){
			this.name=xingming;//ljb.name="";
			this.age=nianling;//ljb.age=50;
			this.hobby=aihao;//ljb.hobby=3500;
		}

	2、反复调用构造函数创建对象
		var ljb=new 构造函数名("廖家兵",50,3500);

   4、访问:
	obj.属性名;
	obj.方法名();

   5、**遍历对象**
	for(var i in obj){
		obj[i];
	}

   6、**this的指向**:
	1、事件中:单个元素 this->这个元素
		   多个元素 this->当前触发元素

	2、函数中:this->当前调用次函数的人
		
	3、构造函数中:this->当前正在创建的对象
	
	4、定时器中:this->window

*****面向对象

*****继承:父对象的成员(属性和方法):子对象可以直接使用

为什么继承:代码重用!节约内存空间!
何时继承:只要多个子对象公用的属性和【方法】,都应该集中定义在父对象中

JS的面向对象是基于原型(父对象)的

什么是原型:保存一类子对象共有属性和共有方法的原型对象(父对象)
1**、**如何去找到原型对象:
	1、对象名.__proto__ - 至少要创建一个对象才可以使用
	2、构造函数名.prototype
	new 构造函数(Object RegExp Date Function String Number Boolean...)
2、在原型对象中添加共有属性和共有方法
	原型对象.属性名=属性值
	原型对象.方法名=function(){}

每一个对象都有一个.__proto__的属性指向着自己的原型
每一个构造函数都有一个.prototype属性指向着自己的原型

面试题:两链一包:
	原型链:自己没有的属性和方法,可以顺着原型链一直向上找,直到最顶层:Object.prototype - 万物皆对象
	作用:查找属性和方法

**自有和共有**
自有:保存在对象本地的
共有:保存在原型对象中的,子对象都可以直接使用

一大批鄙视题:

  1、判断一个属性是自有还是共有:
	1、判断自有:obj.hasOwnProperty("属性名");
		如果结果为true,说明是自有
		如果结果为false,可能是共有也可能是没有

	2、判断共有:2个条件
		obj.hasOwnProperty("属性名")==false;//可能是共有也可能是没有
		"属性名" in obj;//in关键字会查找自己的原型
		if(obj.hasOwnProperty("属性名")==false && "属性名" in obj){
			console.log("共有")
		}else{
			console.log("没有")
		}
	完整的:
		if(obj.hasOwnProperty("属性名")){
			console.log("自有");
		}else{
			if(obj.hasOwnProperty("属性名")==false && "属性名" in obj){
				console.log("共有")
			}else{
				console.log("没有")
			}
		}

  2、修改/删除属性
	自有:修改:obj.属性名=新值;
	      删除:delete obj.属性名;

	共有:修改:千万不要在本地做操作,那会导致在本地添加上一个同名属性,优先使用自己的,但并没有修改原型对象
	      删除:千万不要在本地做操作,那会导致白做没有任何效果
	      强调:一定要找到原型再做操作

  3、为一类人添加方法:
	比如:最常见的一道题:为老IE的数组添加indexOf方法 - 原本只有字符串可以使用,是后续升级数组才能使用的
		if(Array.prototype.indexOf === undefined){//老IE
			Array.prototype.indexOf = function(key,starti){
				starti===undefined&&(starti=0);
				for(var i=starti;i<this.length;i++){
					if(this[i]==key){
						return i;
					}
				}
				return -1;
			}
		}
	
	比如:为一人添加共有方法
		构造函数名.prototype.函数名=function(){
			this->函数中的代表当前调用此函数的对象
		}

   4、判断x是不是一个数组:41、判断当前x对象是否是继承自Array.prototypeArray.prototype.isPrototypeOf(x);
		true说明是一个数组

	2、判断当前x对象是否是由此构造函数所创建
		x instanceof Array
		true说明是一个数组

	3Array.isArray(x); - 只有数组才有此方法
		true说明是一个数组

	4、最麻烦,但是我个人最喜欢
	   在Object的prototype中保存着最原始的toString方法
	   原始的toString输出的结果:[object 构造函数名]
	***多态:子对象觉得父对象提供的方法不好用,可以再本地定义一个同名成员,优先使用离自己更近的方法
		 同一个函数名,但根本不是同一个方法
	   固定套路:
		 if(Object.prototype.toString.apply(arr)==="[object Array]"){
			数组
		 }
	
   5、如何设置自定义继承
	设置单个对象的继承:
		obj.__proto__=新对象

	设置多个对象的继承:
		构造函数名.prototype=新对象
		注意时机:在创建对象之前就设置好父对象