JavaScript复习2
- JS-正则表达式
- JSOOP-高级特征
- JSOOP-定义类和属性(封装)
- JSOOP-继承
- JSOOP-多态
- 手写Jquery
正则表达式
正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")。
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。
正则表达式是繁琐的,但它是强大的,学会之后的应用会让你除了提高效率外,会给你带来绝对的成就感。只要认真阅读本教程,加上应用的时候进行一定的参考,掌握正则表达式不是问题。
许多程序设计语言都支持利用正则表达式进行字符串操作。
语法
语法一var zz1=/abc/;
语法二var zz2=new RegExp('abc');
test验证
test(验证的字符串) 返回值 true false
var zz1=/abc/;
var zz2=new RegExp('abc');
console.log(zz1.test('abc')); //true
console.log(zz1.test('123abc1234')); //true
console.log(zz1.test('123ab123')); //false
边界符号
^开头 $结尾
var reg=/^abc/;//以abc开头
console.log(reg.test('asdabc'));
var reg2=/abc$/;//以abc结尾
var reg3=/^abc$/;//以abc开头和结尾
console.log(reg2.test('abc'));//true
console.log(reg2.test('123abcsd'));//false
console.log(reg2.test('abc456'));//false
console.log(reg2.test('123abc'));//true
集合
[abc]多个里选择一个
var reg=/[abc]/; //包含abc其中一个
console.log(reg.test("temo"));//false
console.log(reg.test("aoduola"));//true
console.log(reg.test("baowan"));//true
[a-h]abcdefgh
var reg=/[a-h]$/; //a~h范围内的结尾
console.log(reg.test("temo"));//false
console.log(reg.test("aoduola"));//true
console.log(reg.test("baowan"));//false
[可以写汉字的范围]
var hz=/^[\u4e00-\u9fa5]{2,8}$/;//2~8个汉字
console.log(hz.test('积分')); //true
console.log(hz.test('积分分子'));//true
console.log(hz.test('超级厉害无敌帅气'));//true
console.log(hz.test('积分123'));//false
[^abc]排除
console.log("------------------------排除");
var reg=/^[^a-zA-Z0-9_-]$/;//排除这些范围
console.log(reg.test("a")); //false
console.log(reg.test("&")); //true
量词
*表示0次或多次
console.log("----------------------量词");
var reg=/^a*$/;//*表示0次或多次
console.log(reg.test('a'));//true
console.log(reg.test(''));//true
+表示一次或多次
var reg1=/^a+$/;//+表示一次或多次
console.log(reg1.test('a'));//true
console.log(reg1.test(''));//false
?表示零次或一次
var reg3=/^a?$/;//?表示零次或一次
console.log(reg3.test('a'));//true
console.log(reg3.test(''));//true
console.log(reg3.test('aaa'));//false
{n}匹配n次 {n,}至少n次 {n,m}至少n次至多m次
var reg4=/^bo{2}m$/;//b开头o为两次m结尾
console.log(reg4.test('bom')); //false
console.log(reg4.test('boom')); //true
console.log(reg4.test('booooom'));//false
元字符
常用的元字符
\d代表数字
\D代表非数字
\w匹配字母数字下划线等价于[A-Z0-9a-z]
\W匹配非字母数字下划线等价于[^A-Z0-9a-z]
\t \r \n \f ==\s 任何空白字符,包括空格、换行、换页、回车、制表符
.除\r\n外任何字符
()括起来的代表一个整体
修饰符
修饰符 | 描述 |
---|---|
i | 将匹配设置为不区分大小写,搜索时不区分大小写: A 和 a 没有区别。 |
g | 查找所有的匹配项。 |
m | 使边界字符 ^ 和 $ 匹配每一行的开头和结尾,记住是多行,而不是整个字符串的开头和结尾 |
s | 默认情况下的圆点 . 是 匹配除换行符 \n 之外的任何字符,加上 s 修饰符之后, . 中包含换行符 \n。 |
正则替换
//replace既支持字符串,也支持正则表达式
//正则替换
var t="今天真鸡儿冷...WC";
var reg=/鸡儿|WC/g;
var ok=t.replace(reg,"TMD");//replace既支持字符串,也支持正则表达式
console.log(ok)
正则匹配
match(正则表达式)匹配出对应的字符串以数组的形式打印
//正则匹配
var st="中国移动10086 中国电信10000 中国联通10010";
var mval=st.match(/\d{5}/g);
console.log(mval);
//获取年月日 ()分组
//获取年月日 ()分组
var d='2005-10-13';
var data=d.match(/(\d{4})-(\d{2})-(\d{2})/);
console.log(data);
console.log(RegExp.$1);//年
console.log(RegExp.$2);//月
console.log(RegExp.$3);//日
JSOOP-高级特征
对象本质可以理解为属性的集合,对象的属性包括数据属性和访问器属性
数据属性
数据属性:它包含的是一个数据值的位置,可以对数据值进行读写
四大特征
- value值
- writable表示是否可写,默认true,如果为false,则表示当前属性只读不可修改
- enumerable表示是否可枚举,默认true如果为false,则在for…in中不会被遍历
- configurable表示是否为可配置的,默认true,如果为false,则不能删除,而且不能再改回true
obj有两个方法
定义属性状态defineProperty(obj,属性名,{})
获取属性描述对象getOwnPropertyDescriptor(obj,属性名)
获取属性描述对象
语法:Object.getOwnPropertyDescriptor(obj,'属性名');
例如:var p1=Object.getOwnPropertyDescriptor(o1,'name');
这样就得到了name的属性对象
定义属性状态
语法:Object,defineProperty(obj,属性名,{})
例如:
Object.defineProperty(o1,'name',{
"writable":false,//name属性不可修改
"enumerable":false//name属性不可枚举
})
这样就将name属性设置成不可修改且不可枚举了.
writable实例
var o1={};
o1.name="csdn";
o1.age=18;
o1.study=function(){
alert("好好学习 天天向上");
}
Object.defineProperty(o1,'name',{
"writable":false,//name属性不可修改
})
//修改属性---修改无效
o1.name='碰磕'; //在严格模式下报错
enumerable实例
Object.defineProperty(o1,'name',{
"enumerable":false//name属性不可枚举
})
for(var at in o1){
// at为属性名
console.log(o1[at]);//得到所有属性的值但得不到name的
//由于name被禁止枚举
}
configurable实例
当设置为不可配置时之后就不可以改回true了
//属性不能删除
Object.defineProperty(o1,'age',{
"configurable":false//修改成不可配置
})
delete o1.age;//删除无效
console.log(o1);
//不可逆的!!!
Object.defineProperty(o1,'age',{
"configurable":true//修改成可配置
})
访问器属性
访问器属性是专门保护数据属性的特殊属性,不实际存储数据
分为getter和setter访问器
get方法负责读取变量值
set方法负责修改变量值
四大特征
- [[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性、或者能否把属性修改为数据属性。默认值是true。
- [[Enumerable]]:表示能否通过for-in循环返回属性。默认值是true。
- [[Get]]:在读取属性时调用的函数。默认值是undefined。
- [[Set]]:在写入属性时调用的函数。默认值是undefined。
实例
/*
*访问器属性
*/
var stu={
id:1,
name:'碰磕',
salary:8000
};
Object.defineProperty(stu,'bank',{
get:function(){
console.log("get方法获取");
return this.salary;
},
set:function(val){
console.log("给stu赋值");
this.salary+=val;
}
})
//测试
stu.bank=1000;//自动调用set方法
console.log(stu.bank);//自动调用get方法
严格模式
- 不可使用with
- 变量必须声明
- this默认是undefined而不是window
- 为只读变量和不可扩展对象赋值会报错
- 函数的形参不可以同名
- 不可以使用caller和arguments的属性,会报错
语法:'use strict';
代码示例:
'use strict';
var o1={};
o1.name="csdn";
o1.age=18;
o1.study=function(){
alert("好好学习 天天向上");
}
//with
with(o1){ //严格模式下不可使用会报错
console.log(name);
console.log(age);
}
//形参不同名,this是值谁
//方法this是谁???window undefined
function test(a,a){//严格模式下形参不可同名
console.log(this);//严格模式下是undefined
console.log(a+a);
}
test(1,2);//报错
// arguments的使用
//没写参数
//arguments.callee==函数本身
function mylist(){
console.log(arguments.callee);//等于函数本身,严格模式下不可使用(报错)
let n=arguments.length;//得到参数的个数
for(var i=0;i<n;i++){
console.log(arguments[i]);
}
}
mylist('参数一号','参数二号','参数三号')
//caller的使用指向函数的调用者
function china(){
hunan()
}
function hunan(){
console.log("我代表湖南");
console.log("调用者:"+hunan.caller);
}
china() // 严格模式下报错caller
总结
- 通过修改属性的四大特征来保护属性
- 数据属性可以控制对象属性的只读,遍历或删除特征
- 访问器属性可以通过自定义逻辑来设置和获取变量的值
JSOOP-定义类和属性(封装)
类似于java中的
private私有属性 public公有属性 protected受保护的属性
static静态属性
定义类var Animal=function(name,type){}
私有属性方法
var Animal=function(name,type){
//private私有属性
var _type=type;
//private私有方法
var isAnimal=function(){
console.log("私有方法"+_type);
}
isAnimal();
}
受保护属性方法
在类中添加
//protected受保护的属性
var _age=0;
//访问器
Object.defineProperty(this,"age",{
get: function(){
console.log("查看年龄...");
return this._age;
},
set: function(val){
//保护
if(val>100){
this._age=20;
}else{
this._age=val;
}
}
});
公有属性方法
在类中添加
//公有属性和方法
this.type=type;
this.sayhello=function(){
console.log("Hello JSOOP");
}
静态属性方法
//静态属性static
Animal.number=90;
Animal.count=function(){
console.log("静态方法动物总数"+Animal.number);
}
console.log(Animal.number);
Animal.count();
//对象不能用静态属性
直接通过类名.属性或者方法名调用
对象不能用静态属性
添加原型的两种方式
方式一1、Animal.prototype.属性名="值"; 2、Animal.prototype.方法名=function(){}
方式二:Animal.prototype={属性名:值,方法名:函数}
JSOOP-继承
继承父类的方法属性,在java中用到关键词
extends
方案一:拷贝继承
通俗易懂(效率低)
给object编写一个copy方法
相对于将把b对象的所有值复制给a对象 b—>a
Object.copy=function(a,b){
for(var attr in b){
a[attr]=b[attr]; //a.name=a[name]
}
return a;
}
再编写一个继承方法
//继承方法
Object.prototype.extends=function(o){
return Object.copy(this,o); //当前对象继承o
}
示例1
var temo={
name:"temo",
age:18,
fun:function(){
console.log("方法");
}
};
var dema={};
dema.extends(temo);//继承
console.log(temo);
console.log(dema);
dema.fun()
继承成功并且可调用fun方法
示例2
//形状类(继承示例2)
var Shape=function(){
this.draw=function(){
//调用下方空方法
this._draw();
}
//空方法
this._draw=function(){}
}
//矩形
var Rect=function(){};
// var xz=new Shape();//父类对象
Rect.prototype=(new Shape()).extends({
width:100,
height:200,
_draw:function(){
console.log("画个矩形");
}
});
var rec=new Rect();
rec._draw();//打印出两个矩形
继承并且添加两个属性以及重写_draw方法…ok
方案二:原型链继承
简便快捷(不支持多重继承)
//定义一个动物类
function Animal(name){
//属性
this.name=name||'Animal';
//实例方法
this.sleep=function(){
console.log(this.name+"正在睡觉!");
}
}
//原型方法
Animal.prototype.eat=function(food){
console.log(this.name+'正在吃:'+food);
};
//--------------上面是父类------------------
// 原型链继承
function Cat(){}
Cat.prototype=new Animal('加菲猫');
示例
cat.eat("🐟")
cat.sleep()
console.log(cat instanceof Animal);//true
console.log(cat instanceof Cat);//true
方案三:构造继承
调用父类的构造方法(支持多重继承)
只能执行实例函数,原型函数执行不了
function Ufo(){
this.lay=function(){
console.log("反重力飞行");
}
}
function Cat(name){
Animal.call(this);//调用父类的构造方法
Ufo.call(this);//多重继承
this.name=name||'小白';
}
var cat=new Cat('波斯猫')
cat.sleep()
cat.lay()
console.log(cat instanceof Animal);//false
console.log(cat instanceof Ufo);//false
console.log(cat instanceof Cat);//true
方案四:实例继承
类中new父类返回父类
function Cat(name){
var obj=new Animal();
obj.name=name||"阿里巴巴";
return obj;
}
var cat=new Cat();
cat.eat("🐟");
cat.sleep();
console.log(cat instanceof Animal);//true
console.log(cat instanceof Cat);//false
方案五:组合继承(原型链+构造函数方式)
解决了构造函数中不可调用原型函数的缺点
并且可以多重继承
缺点:调用了两次构造方法
function Cat(name){
Animal.call(this);
this.name=name||'组合';
}
Cat.prototype=new Animal();
var cat=new Cat("小白");
cat.sleep();
cat.eat("饭");
console.log(cat instanceof Animal);//true
console.log(cat instanceof Cat);//true
方案六:寄生继承(力荐)
包含了组合继承的所有优点且解决了它的缺点
function Cat(name){
Animal.call(this);
this.name=name||'终极组合';
}
(function(){
var Super=function(){};
Super.prototype=Animal.prototype;
Cat.prototype=new Super();
})();
var cat=new Cat("小红");
cat.sleep();
cat.eat("喝粥");
console.log(cat instanceof Animal);//true
console.log(cat instanceof Cat);//true
//--------------上面是寄生继承(原型链+构造函数方式[超推荐解决了组合继承的缺点])------------------
JSOOP-多态
同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性。 简单的说:就是用基类的引用指向子类的对象。
var Rect=function(){
this.draw=function(){
console.log("画个矩形");
}
}
var Circle=function(){
this.draw=function(){
console.log("画个圆形");
}
}
//模拟多态
function test(obj){
obj.draw();
}
test(new Circle())
手写Jquery
Jquery写法$("")
$是什么?? 函数
$() 返回值? 对象
手写jq实现 $(“h1”).css(“color”,“red”);
对象与数组合并Array.prototype.push.apply(stu,arr1);//(对象,数组)
(function(){
//主方法返回对象
var Jquery=function(selector){
return new Jquery.prototype.Init(selector);
}
//给原型加载Init
Jquery.prototype={
Init:function(selector){
console.log("选择器"+selector);
//找到多个dom 例如class、标签查找
var sz=document.querySelectorAll(selector);
Array.prototype.push.apply(this,sz);//将得到的dom节点放入this中
return this;//Init
},
css:function(attr,val){
console.log("属性"+attr);
console.log("值"+val);
for(var i=0;i<this.length;i++){ //this.length==Init.length
if(val==undefined){
return this[i].style[attr];
}else{
this[i].style[attr]=val;
}
}
//实现链式
return this;
}
}
//将Jquery的原型赋值给init;
Jquery.prototype.Init.prototype=Jquery.prototype;
//挂载到window对象上
window.$=Jquery;
})();
$(".lang").css("color","pink").css("fontSize","50px")//xxx.style[color]="red"--->js
Init:得到dom点的方法
将Jquery挂载到window对象上,这样在外边就能调用
将Jquery的原型赋值给init这样Jquery的css方法Init也能调用
css:传一个属性得到该属性值,传两个则修改,支持链式
取出选择器找到的第n个元素eq
eq:function(n){
this[0]=this[n];
this.length=1;
return this;
},
html未传值则得到html文本信息,传值则修改html文本信息
html:function(val){
for(var i=0;i<this.length;i++){
if(val==undefined){
return this[i].innerHTML;
}else{
this[i].innerHTML=val;
}
}
return this;
}
attr实现得到属性值,改变属性值[可链式操作]
并且可以传入对象进行赋值
//实现jquery中的attr方法,要求可以做链式操作。
attr:function(attr,val){
// console.log(typeof attr);
if(typeof attr =="object"){
for(let j in attr){
// console.log("j="+j+"attr="+attr[j]);
for(var i=0;i<this.length;i++){
this[i].setAttribute(j,attr[j]);
}
}
}else{ //参数是string型
for(var i=0;i<this.length;i++){
if(val==undefined){
return this[0].getAttribute(attr);
}else{
this[i].setAttribute(attr,val);
}
}
}
return this;
}
each遍历
each:function(fn){ //参数是个函数
for(var i=0;i<this.length;i++){
fn(i,this[i]);//调用函数
}
}
//each遍历
$("p").each(function(index,item){
console.log(index + "----" + item.innerHTML);
});
给自己写的jq添加继承功能使得别人可以add功能
trim去除字符串空格
//可拓展方法
Jquery.extends=function(obj){
for(var attr in obj){
this[attr]=obj[attr];
}
return this;
}
//给自己写的jq加功能
$.extends({
//去除两端空格
trim:function(str){
return str.replace(/^\s+|\s+$/g,'');//(正则,替换字符)
}
});
//示例
var t=' hello world ';
console.log(t+"---"+t.length);
var ok=$.trim(t);
console.log(ok+"---"+ok.length);//去除空格后长度
测试成功,ojbk------------>>>
练习
正则表达式练习
//手机号
//账号是否合法(字母开头,允许5~16字节,允许字母数字下划线)
//密码(长度在6~18之间,只能包含字母、数字、下划线)
//qq号
//练习
//手机号
var tel=/^[13|15|18|14][0-9][0-9]{4}[0-9]{4}/;
console.log(tel.test('15770623252'));
//账号是否合法(字母开头,允许5~16字节,允许字母数字下划线)
var user=/^[a-z|A-Z][a-z|A-Z|0-9|_]{4,15}/;
console.log(user.test('A_13'));
//密码(长度在6~18之间,只能包含字母、数字、下划线)
var pwd=/^[a-z|A-Z|0-9|_]{6,18}/;
console.log(pwd.test('Aaa_13'));
//qq号
var qq=/^[1-9][0-9]{4,}/;
console.log(qq.test('3038324746'));
匹配图片路径
var html = `
<li class="list-item"><div class="equipment-item"><div class="prop-box"><img src="https://game.gtimg.cn/images/lol/act/img/item/1033.png" alt="抗魔斗篷"></div> <p class="prop-name">抗魔斗篷</p> <div class="price"><i class="icon-gold"></i> <span>450</span></div></div></li>
<li class="list-item"><div class="equipment-item"><div class="prop-box"><img src="https://game.gtimg.cn/images/lol/act/img/item/1037.png" alt="十字镐"></div> <p class="prop-name">十字镐</p> <div class="price"><i class="icon-gold"></i> <span>875</span></div></div></li>
`
var pic=/https:\/\/.*\.png|jpg$/g;
var src=html.match(pic);
console.log(src);
高级特性练习
- 创建一个猫对象,通过defineProperty给它定义name数据属性,值为大黄,不可修改,可枚举可配置,
color数据属性,值为黄色,可修改可枚举可配置,weight访问器属性,可枚举可配置。 - 创建一个学生stu对象,通过defineProperty定义一个score访问器属性,
当运行stu.score = 5;时打印出’成绩进步了5分’,当运行var s = stu.score;时打印出‘成绩是95分’ - 创建一个car对象,通过defineProperty定义一个price访问器属性,
当运行car.price = 9;时打印出’售车打9折’,当运行var p = car.price;时打印出‘价格是999999元’
第一题猫对象
//1
var cat={
"name":"大黄",
"color":"黄色",
"tz":10
};
Object.defineProperty(cat,'name',{
"writable":false,//name属性不可修改
})
Object.defineProperty(cat,'weight',{
get:function(){
return this.tz;
},
set:function(val){
return this.tz+=val;
}
})
cat.weight=20;
console.log(cat.weight);
第二题stu对象
//2
var stus={};
let grads=90;
Object.defineProperty(stus,'score',{
get:function(){
console.log("成绩是"+grads+"分");
return grads;
},
set:function(val){
console.log("成绩进步了"+val+"分");
return grads+=val;
}
})
stus.score=6;
stus.score;
第三题car对象
//3
var car={};
let qian=1111110;
Object.defineProperty(car,'price',{
get:function(){
console.log("价格是"+qian+"元");
return qian;
},
set:function(val){
console.log("售车打"+val+"折");
return qian=qian*(val/10);
}
})
car.price = 9;
car.price;
继承、封装、多态练习
创建一个Person类,包含name公开的属性,age受保护的属性,这个值只能是数字,私有的属性account。
var Person=function(name){
this.name=name;//公开的属性
var account="私房钱";//私有属性
var _age=0;//受保护的
var num=/\d/;
Object.defineProperty(this,"age",{
get:function(){
return _age;
},
set:function(val){
if(num.test(val)){
_age=val;
}else{
console.log("age只能是数字");
}
}
})
}
创建一个showMoney私有的方法,在这个方法中打印出account的值。
var showMoney=function(){ //私有方法showMoney
console.log("account的值:"+account);
}
创建一个showMsg公开的方法,在这个方法中打印出name和age,并且调用showMoney方法。
this.showMsg=function(){ //公有方法showMsg()
console.log("name:"+this.name+";age:"+this.age);
showMoney();//调用
}
创建一个交通类Trafic和它的两个子类Car和Bike,通过多态实现每种交通工具的run方法。
Object.copy=function(a,b){
for(var attr in b){
a[attr]=b[attr];
}
return a;
}
Object.prototype.extends=function(o){
return Object.copy(this,o)
}
var ren1=new Person("肖");
ren1.age="2";
ren1.showMsg();
//继承
var Trafic=function(){
this._run=function(){
//调用下方空方法
this.run();
}
//空方法
this.run=function(){}
}
var Car=function(){}
var Bike=function(){}
Car.prototype=(new Trafic()).extends({
run :function(){
console.log("汽车动起来.....");
}
});
Bike.prototype=(new Trafic()).extends({
run :function(){
console.log("自行车GoGoGo.....");
}
});
var car1=new Car();
var bike1=new Bike();
car1.run()
bike1.run()
//多态
var Trafic1=function(obj){
obj.runn();
}
var Car1=function(){};
Car1.prototype.runn=function(){
console.log("开车回家!");
}
Trafic1(new Car1());
var Bike1=function(){};
Bike1.prototype.runn=function(){
console.log("骑自行车回家!");
}