目录
- 基本数据类型(Undefined,Null,Boolean,Number、String、Symbol【ES6】)
- 引用数据类型(Object、数组、函数)
深拷贝和浅拷贝只针对Object和数组这两种引用数据类型
1.浅拷贝
浅拷贝:创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本数据类型,拷贝的就是基本数据类型的值;如果属性是引用类型,拷贝的就是内存地址 (指向同一个内存空间),所以如果其中一个对象改变了,就会影响到另一个对象。
分清浅拷贝和赋值的区别:
把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。
//原对象
var obj = {
//第一层
a:1,
arr:['a','b'],
say:function(){
console.log('hello');
},
obj2:{
//第二层
a:2,
arr:['c','d'],
obj3:{
//第三层
say:function(){
console.log('world');
}
}
}
};
//新对象
var newObj={};
//把a对象中的所有的内容复制到对象b中
function extend(a,b) {
for(var key in a){
b[key]=a[key];
}
}
extend(obj,newObj);
//改变新对象的属性和方法(第一层)
newObj.a='一';
newObj.arr[1]='B';
newObj.say=function(){
console.log('new hello');
};
//改变新对象的属性和方法(第二层及更深层)
newObj.obj2.a='二';
newObj.obj2.arr[1]='D';
newObj.obj2.obj3.say=function(){
console.log('new world');
};
//打印新数组
console.dir(newObj);
newObj.say();
newObj.obj2.obj3.say();
//打印原数组
console.dir(obj);
obj.say();
obj.obj2.obj3.say();
左边为新数组,右边为原数组:
结果:第一层中为基本数据类型的数据,其值没有随着另一个对象的值改变而改变,但第一层中数组的值改变了(数组是引用类型);而第二层及更深层中,所有的值都一同改变了(对象是引用类型,那么它的所有属性和方法也都会变)。
2.深拷贝
深拷贝:将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的内存存放新对象,且修改其中一个对象不会影响另一个对象。
//原对象
var obj = {
//第一层
a:1,
arr:['a','b'],
say:function(){
console.log('hello');
},
obj2:{
//第二层
a:2,
arr:['c','d'],
obj3:{
//第三层
say:function(){
console.log('world');
}
}
}
};
//新对象
var newObj={};
//通过函数实现,把对象a中的所有的数据深拷贝到对象b中
function extend(a,b) {
for(var key in a){
//先获取a对象中每个属性的值
var item=a[key];
//判断这个属性的值是不是数组
if(item instanceof Array){
//如果是数组,那么在b对象中添加一个新的属性,并且这个属性值也是数组
b[key]=[];
//调用这个方法,把a对象中这个数组的属性值复制到b对象的数组属性中
extend(item,b[key]);
}else if(item instanceof Object){//判断这个值是不是对象类型的
//如果是对象类型的,那么在b对象中添加一个属性,是一个空对象
b[key]={};
//再次调用这个函数,把a对象中这个对象的属性值复制到b对象的对象属性中
extend(item,b[key]);
}else{
//如果值是普通的数据,直接复制到b对象的这个属性中
b[key]=item;
}
}
}
extend(obj,newObj);
//改变新对象的属性和方法(第一层)
newObj.a='一';
newObj.arr[1]='B';
newObj.say=function(){
console.log('new hello');
};
//改变新对象的属性和方法(第二层及更深层)
newObj.obj2.a='二';
newObj.obj2.arr[1]='D';
newObj.obj2.obj3.say=function(){
console.log('new world');
};
//打印新数组
console.dir(newObj);
newObj.say();
newObj.obj2.obj3.say();
//打印原数组
console.dir(obj);
obj.say();
obj.obj2.obj3.say();
左边为新数组,右边为原数组:(可以看出原数组没有受到任何影响)
3.遍历DOM树
<h1>遍历 DOM 树</h1>
<p style="color: green;">Tip: 可以在遍历的回调函数中任意定制需求</p>
<div>
<ul>
<li>123</li>
<li>456</li>
<li>789</li>
</ul>
<div>
<div>
<span>haha</span>
</div>
</div>
</div>
<div id="demo_node">
<ul>
<li>123</li>
</ul>
<p>hello</p>
<h2>world</h2>
<div>
<p>sfdbg</p>
<h3>
<span>mnjjlk</span>
</h3>
</div>
</div>
<script>
//获取页面中的根节点--根标签
var root=document.documentElement;//html
//函数遍历DOM树
//根据根节点,寻找所有子节点
function forDOM(root1) {
//获取根节点中所有的子节点
var children=root1.children;
//调用遍历所有子节点的函数
forChildren(children);
}
//把所有子节点(某个节点的子节点集)中的所有的子节点显示出来
function forChildren(children) {
//遍历所有的子节点
for(var i=0;i<children.length;i++){
//每个子节点
var child=children[i];
//显示每个子节点的名字
show(child);
//判断child下面有没有子节点,如果还有子节点,那么就继续的遍历
child.children&&forDOM(child);
}
}
//函数调用,传入根节点
forDOM(root);
//显示节点名字
function show(node) {
console.log("节点的名字:"+node.nodeName);
}
</script>
4.正则表达式(Regular Expression)
正则表达式的作用:匹配字符串
正则表达式的组成:是由普通字符(包括大小写的字母和数字)和一些元字符组成的一个式子
元字符:
. 除了\n以外的任意的一个字符
[] 范围;可以把正则表达式中元字符的意义去掉:[.] 就是一个.
[0-9]:0到9之间任意的一个数字
[1-7]:1到7之间任意的一个数字
[a-z]:所有小写字母中任意的一个
[A-Z]:所有大写字母中任意的一个
[a-zA-Z]:所有字母(大小写)中任意的一个
[0-9a-zA-Z]:所有的数字或者字母(大小写)中的一个
| 或者
[0-9]|[a-z]:要么是一个数字,要么是一个小写的字母
() 分组,提升优先级
([0-9])([1-5])([a-z]) :三组, 从最左边开始计算
限定符(也是元字符):限定前面的表达式出现的次数
* 前面的表达式出现了0次-多次
[a-z][0-9]*:小写字母中的任意一个,后面是要么是没有数字的,要么是多个数字的,可匹配 "fdsfs3223323"
+ 前面的表达式出现了1次-多次
[a-z][9]+:小写字母中的任意一个,后面最少一个9,或者多个9,可匹配"fesfewww9fefds"
? 前面的表达式出现了0次-1次,最少是0次,最多1次;另一个含义:阻止贪婪模式(趋向于最大长度匹配,非贪婪匹配:匹配到字符就好,最少地匹配)
{} 更加明确前面的表达式出现的次数
{5,10} 表示的是前面的表达式出现了5次到10次
{4} 前面的表达式出现了4次
{0,} 和*一样
{1,} 和+一样
{0,1} 和?一样
^ 在[]外面时表示:以什么开始;在[]里面时表示:取非(取反)
^[0-9] 以数字开头
[^0-9] 取反,非数字
$ 以什么结束
[0-9][a-z]$ 必须以小写字母结束
^[0-9][a-z]$ 相当于是严格模式 只能匹配"4f"这样的一个数字开头,一个小写字母结尾的字符
\d 匹配一个数字,等价于[0-9]
\D 匹配一个非数字字符,等价于[^0-9]
\s 匹配一个空白字符,包括空格、制表符、换页符和换行符
\S 匹配一个非空白字符
\w 匹配一个非特殊字符(字母、数字或者下划线即单字字符),等价于 [A-Za-z0-9_]
\W 匹配一个特殊字符(非单字字符),等价于 [^A-Za-z0-9_]
\b 单词的边界
4.1 正则表达式练习
1.身份证的正则表达式
15位或者18位
([1-9][0-9]{14})|([1-9][0-9]{16}[0-9xX]) 或者 ([1-9][0-9]{14})([0-9]{2}[0-9xX])?
2.座机号码的正则表达式
010-19876754 0431-87123490
[0-9]{3,4}[-][0-9]{8}或\d{3,4}[-]\d{8}
3.qq号码的正则表达式
[1-9][0-9]{4,10}
4.邮箱的正则表达式
sd2113_3.-fd@itcast.com.cn
[0-9a-zA-Z_.-]+[@][0-9a-zA-Z_.-]+([.][a-zA-Z]+){1,2}
4.2 创建正则表达式对象
通过构造函数创建正则表达式对象:
- 两个参数:new RegExp('正则表达式主体','修饰符(可选)');
- 一个参数:new RegExp(/正则表达式主体/修饰符(可选));
- new RegExp('abc','i');
- new RegExp(/abc/i);
正则表达式修饰符
- i:不区分大小写
- g:执行全局匹配(查找所有匹配,而不是在找到第一个匹配后停止)
4.3 正则表达式案例
4.3.1 验证密码强度
<style type="text/css">
#dv {
width: 300px;
height: 200px;
position: absolute;
left: 300px;
top: 100px;
}
.strengthLv0 { /*初始*/
height: 6px;
width: 120px;
border: 1px solid #ccc;
padding: 2px;
}
.strengthLv1 { /*弱*/
background: red;
height: 6px;
width: 40px;
border: 1px solid #ccc;
padding: 2px;
}
.strengthLv2 { /*中*/
background: orange;
height: 6px;
width: 80px;
border: 1px solid #ccc;
padding: 2px;
}
.strengthLv3 { /*强*/
background: green;
height: 6px;
width: 120px;
border: 1px solid #ccc;
padding: 2px;
}
</style>
<body>
<div id="dv">
<label for="pwd">密码</label>
<input type="text" id="pwd" maxlength="16">
<div>
<em>密码强度:</em>
<em id="strength"></em>
<div id="strengthLevel" class="strengthLv0"></div>
</div>
</div>
<script>
/*
*
* 密码: 数字,字母,特殊符号
*
* 密码: 只有数字,或者是只有字母,或者是只有特殊符号——1级——弱
* 两两组合: 数字和字母,数字和特殊符号,字母和特殊符号——2级——中
* 三者都有: 数字和字母和特殊符号——3级——强
*
* */
function my$(id) {
return document.getElementById(id);
}
/*//获取文本框注册键盘抬起事件
my$("pwd").onkeyup = function () {
//每次键盘抬起都要获取文本框中的内容,验证文本框中的内容,得到一个级别,然后下面的div显示对应的颜色
//如果密码的长度是小于6的,没有必要判断
if (this.value.length >= 6) {
var lvl = getLvl(this.value);
if (lvl == 1) {
//弱
my$("strengthLevel").className = "strengthLv1";
} else if (lvl == 2) {
my$("strengthLevel").className = "strengthLv2";
} else if (lvl == 3) {
my$("strengthLevel").className = "strengthLv3";
} else {
my$("strengthLevel").className = "strengthLv0";
}
} else {
my$("strengthLevel").className = "strengthLv0";
}
};*/
//获取文本框注册键盘抬起事件
my$("pwd").onkeyup = function () {
//每次键盘抬起都要获取文本框中的内容,验证文本框中有什么东西,得到一个级别,然后下面的div显示对应的颜色
//如果密码的长度是小于6的,没有必要判断
var lvl = getLvl(this.value);
/*if (this.value.length >= 6) {
my$("strengthLevel").className = "strengthLv" + lvl;
} else {
my$("strengthLevel").className = "strengthLv0";
}*/
my$("strengthLevel").className = "strengthLv" + (this.value.length >= 6 ?lvl: 0);
};
//根据密码,返回对应的级别
function getLvl(pwd) {
var lvl = 0;//默认是0级
//密码中是否有数字,或者是字母,或者是特殊符号
if (/[0-9]/.test(pwd)) {
lvl++;
}
//判断密码中有没有字母
if (/[a-zA-Z]/.test(pwd)) {
lvl++;
}
//判断密码中有没有特殊符号
if (/[^0-9a-zA-Z_]/.test(pwd)) {
lvl++;
}
return lvl;//最小1,最大3
}
</script>
</body>
4.3.2 验证邮箱
<body>
请输入邮箱:<input type="text" value="" id="email"/>*<br/>
<script>
//如果输入的是邮箱,那么背景颜色为绿色,否则为红色
//获取文本框,注册失去焦点的事件
document.getElementById("email").onblur=function () {
//判断这个文本框中输入的是不是邮箱
var reg = /^[0-9a-zA-Z_.-]+[@][0-9a-zA-Z_.-]+([.][a-zA-Z]+){1,2}$/;
if (reg.test(this.value)) {
this.style.backgroundColor = "green";
} else {
this.style.backgroundColor = "red";
}
};
</script>
</body>
4.3.3 验证中文名
<body>
请输入名字:<input type="text" value="" id="userName"/>*<br/>
<script>
//是中文名字,则绿色,否则红色
document.getElementById("userName").onblur = function () {
var reg = /^[\u4e00-\u9fa5]{2,6}$/;
if (reg.test(this.value)) {
this.style.backgroundColor = "green";
} else {
this.style.backgroundColor = "red";
}
};
//[\u4e00-\u9fa5] [一-龥]
</script>
</body>
4.3.4 验证表单
<style type="text/css">
body {
background: #ccc;
}
label {
width: 40px;
display: inline-block;
}
span {
color: red;
}
.container {
margin: 100px auto;
width: 400px;
padding: 50px;
line-height: 40px;
border: 1px solid #999;
background: #efefef;
}
span {
margin-left: 30px;
font-size: 12px;
}
</style>
</head>
<body>
<div class="container" id="dv">
<label for="qq">Q Q</label><input type="text" id="qq"><span></span><br/>
<label>手机</label><input type="text" id="phone"><span></span><br/>
<label>邮箱</label><input type="text" id="e-mail"><span></span><br/>
<label>座机</label><input type="text" id="telephone"><span></span><br/>
<label>姓名</label><input type="text" id="fullName"><span></span><br/>
</div>
<script>
function my$(id) {
return document.getElementById(id);
}
//qq的
checkInput(my$("qq"), /^\d{5,11}$/);
//手机
checkInput(my$("phone"), /^\d{11}$/);
//邮箱
checkInput(my$("e-mail"), /^[0-9a-zA-Z_.-]+[@][0-9a-zA-Z_.-]+([.][a-zA-Z]+){1,2}$/);
//座机号码
checkInput(my$("telephone"), /^\d{3,4}[-]\d{7,8}$/);
//中文名字
checkInput(my$("fullName"), /^[\u4e00-\u9fa5]{2,6}$/);
//通过正则表达式验证当前的文本框是否匹配并显示结果
function checkInput(input, reg) {
//文本框注册失去焦点的事件
input.onblur = function () {
if (reg.test(this.value)) {
this.nextElementSibling.innerText = "验证成功";
this.nextElementSibling.style.color = "green";
} else {
this.nextElementSibling.innerText = "验证失败";
this.nextElementSibling.style.color = "red";
}
};
}
</script>
</body>