js学习笔记 day7
## 1.对象的拷贝
<script>
<script>
// 对象的拷贝
var obj1 = {
name: 'zs',
age: 18,
sex: '男'
}
var obj2 = {};
// // 遍历对象中的成员
// for (var key in obj1) {
// // obj1[key]
// obj2[key] = obj1[key];
// }
// // 修改obj1的成员,此时不会影响obj2
// obj1.name = 'xx';
// console.dir(obj2);
// 封装函数 - 把o1 的成员,复制给o2
function copy(o1, o2) {
for (var key in o1) {
o2[key] = o1[key];
}
}
copy(obj1, obj2);
console.dir(obj2);
</script>
### 1.浅拷贝
<script>
<script>
// 对象的拷贝
var obj1 = {
name: 'zs',
age: 18,
sex: '男',
dog: {
name: '金毛',
age: 2,
yellow: '黄色'
}
}
var obj2 = {};
// 封装函数 - 把o1 的成员,复制给o2
// 浅拷贝
function copy(o1, o2) {
for (var key in o1) {
o2[key] = o1[key];
}
}
copy(obj1, obj2);
// 修改obj1中的成员
obj1.name = 'xxxx';
obj1.dog.name = '大黄';
console.dir(obj2);
</script>
### 2.深拷贝
<script>
// 对象的拷贝
/*var obj1 = {
name: 'zs',
age: 18,
sex: '男',
dog: {
name: '金毛',
age: 2,
yellow: '黄色'
},
friends: ['lilei', 'hanmeimei']
}
var obj2 = {};
var arr = [];
console.log(arr instanceof Array);
console.log(arr instanceof Object);
// 深拷贝
function deepCopy(o1, o2) {
for (var key in o1) {
if (o1[key] instanceof Array) {
console.log(key);
// 如果key是数组类型 Array? []
o2[key] = [];
deepCopy(o1[key], o2[key]);
} else if (o1[key] instanceof Object) {
// 如果key是复杂类型 Object? {}
o2[key] = {};
deepCopy(o1[key], o2[key]);
} else {
// 如果key这个属性 是基本类型
o2[key] = o1[key];
}
}
}
deepCopy(obj1, obj2);
// 修改obj1中的成员
obj1.name = 'xxxx';
obj1.dog.name = '大黄';
obj1.friends[0] = 'xxxx';
console.dir(obj1);
console.dir(obj2);*/
function deepClone(obj){
var result;
var oClass=isClass(obj);
if(oClass==="Object"){
result={};
}else if(oClass==="Array"){
result=[];
}else{
return obj;
}
for(var key in obj){
var copy=obj[key];
if(isClass(copy)=="Object"){
result[key]=arguments.callee(copy);//递归调用
}else if(isClass(copy)=="Array"){
result[key]=arguments.callee(copy);
}else{
result[key]=obj[key];
}
}
return result;
}
//判断对象的数据类型
function isClass(o){
if(o===null) return "Null";
if(o===undefined) return "Undefined";
return Object.prototype.toString.call(o).slice(8,-1);
}
var oPerson={
oName:"rookiebob",
oAge:"18",
oAddress:{
province:"beijing"
},
ofavorite:[
"swimming",
{reading:"history book"}
],
skill:function(){
console.log("bob is coding");
}
};
//深度克隆一个对象
var oNew=deepClone(oPerson);
oNew.ofavorite[1].reading="picture";
console.log(oNew.ofavorite[1].reading);
console.log(oPerson.ofavorite[1].reading);
</script>
## 2.bind call 和 apply
<script>
1.bind 方法 ES5中新增的方法
// 函数也是对象
var a = 123;
function fn() {
console.log(this.a);
}
window.fn();
// fn.prototype
// bind 方法 ES5中新增的方法
// 新建一个方法,bind中的第一个参数可以改变函数中的this的指向
// bind并没有调用方法
var o = {a: 'abc'};
var fn1 = fn.bind(o);
fn1(); // 相当于 o.fn()
2. bind的应用
var obj = {
name: 'zs',
fun: function() {
setInterval(function() {
console.log(this.name);
}.bind(this), 1000);
}
}
obj.fun();
btn.onclick = function () {
// 事件处理函数中的this 是触发该事件的对象
// 通过bind 改变事件处理函数中this的指向
}.bind(obj);
</script>
<script>
// call bind apply 改变函数中的this
// 函数是一个对象
// var fn = new Function();
// function fn() {
// }
// 证明fn是Function的实例(对象)
// console.log(fn.__proto__ === Function.prototype);
// console.dir(fn);
function fn(x, y) {
console.log(this);
console.log(x + y);
}
// fn(5, 6); // this->window
// 1 调用函数,改变函数中的this
// 2 第一个参数 设置函数内部this的指向
// 其它参数,对应函数的参数
// 3 函数的返回值 call的返回值就是函数的返回值
// 4 测试
// var obj = {
// name: 'zs'
// }
// fn.call(obj, 5, 6);
// apply 只有两个参数
// 1 调用函数,改变函数中的this
// 2 第一个参数 设置函数内部this的指向
// 第二个参数 是数组
// 3 函数的返回值 apply的返回值就是函数的返回值
// 4 测试
// var obj = {
// name: 'ls'
// }
// fn.apply(obj, [1, 2]);
// bind
// 1 改变函数中的this,不会调用函数,而是把函数复制一份
// 2 第一个参数 设置函数内部this的指向
// 其它参数,对应函数的参数
// 3 函数的返回值 call的返回值就是函数的返回值
// 4 测试
var obj = {
name: 'ww'
}
var f = fn.bind(obj, 5, 5);
f();
</script>
## 3.组合继承(借用构造函数 + 原型继承)
<script>
// 组合继承:借用构造函数 + 原型继承
// 父类型
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
Person.prototype.sayHi = function () {
console.log('大家好,我是' + this.name);
}
// 子类型
function Student(name, age, sex, score) {
// 借用构造函数
Person.call(this, name, age, sex);
this.score = score;
}
// 通过原型,让子类型,继承父类型中的方法
Student.prototype = new Person();
Student.prototype.constructor = Student;
// 学生特有的方法
Student.prototype.exam = function () {
console.log('考试');
}
// var s1 = new Student('zs', 18, '男', 100);
// console.dir(s1);
// var p1 = new Person('ls', 18, '男');
// console.dir(p1);
function Teacher(name, age, sex, salary) {
// 借用构造函数
Person.call(this, name, age, sex);
this.salary = salary;
}
// 通过原型让子类型继承父类型中的方法
Teacher.prototype = new Person();
Teacher.prototype.constructor = Teacher;
var t1 = new Teacher('ww', 30, '男', 100000);
console.dir(t1);
t1.sayHi();
</script>
## 4.原型继承
<script>
// 继承:类型和类型之间的关系
// 学生类型 老师类型 -> Person类型
// 继承目的: 把子类型中共同的成员提取到父类型中,代码重用
// 父类型
function Person() {
this.name = 'zs';
this.age = 18;
this.sex = '男';
}
// 子类型
function Student() {
this.score = 100;
}
Student.prototype = new Person();
Student.prototype.constructor = Student;
var s1 = new Student();
console.log(s1.constructor);
console.dir(s1);
function Teacher() {
this.salary = 3000;
}
// 原型继承: 无法设置构造函数的参数
</script>
## 5.注册事件的兼容处理
<script>
//注册事件的方式
//1. ele.on事件类型 = function(){}
//2. addEventListener(事件类型,事件处理函数,useCapture) 第三个参数默认是false,冒泡阶段执行
//3. attachEvent(事件类型,事件处理函数)
//1.在注册事件的时候,判断浏览器的注册事件的方式,然后直接使用该方式进行注册事件
//复用性太差
//2.将注册事件的代码封装到一个函数中
//每次调用该函数,都会进行浏览器能力检测
//3.在函数中返回函数,让外部函数只执行一次,判断也就只会执行一次
//使用函数内创建的函数返回给外界,就可以重复使用该函数,进行事件的注册
//封装成函数,问题是每次都会判断
// function registeEvent(target, type, handler){
// if(target.addEventListener){
// target.addEventListener(type,handler)
// }else if(target.attachEvent){
// target.attachEvent("on"+type,handler)
// }else{
// target["on"+type] = handler;
// }
// }
//使用更好的方式,避免了多次的判断
//这里存在问题就是
//我们使用统一的方式,进行事件注册
//1、注册的事件的处理函数中的,this指向不一致
//使用addEventListener的方式注册的点击事件的回调函数中的this 指向target
//但是使用attachEvent的方式注册点击事件的回调函数中的this 指向window
//2、3种注册事件的方式中,回调函数内获取事件对象的方式也是不一致的
//要让他们统一,
//在第二种的事件注册方式(attachEvent)中,手动给handler传递window.event
function createEventRegister(){
if(window.addEventListener){
return function(target, type, handler){
// this ---> window
target.addEventListener(type,handler)
}
}else if(window.attachEvent){
return function(target, type, handler) {
target.attachEvent("on" + type, function(){
handler.call(target, window.event);
})
}
}else{
return function(target, type, handler) {
target["on" + type] = handler;
}
}
}
var registeEvent = createEventRegister();
window.onload =function () {
var div = document.getElementById("div1");
registeEvent(div,"click",function(e){
console.log(e);
console.log(this);
//this---->该事件的触发对象
alert("太阳天空照,花儿对我笑,小鸟说:完了")
})
}
// div.addEventListener("click",function(e){
// this
// e.screenX;
// })
//
// div.attachEvent("onclick".function(){
//// this--->window
// window.event.screenX
// })
</script>
## 6.注册时间兼容处理的分析
<script>
window.onload =function () {
var div = document.getElementById("dvd1");
function huidiao(e){
console.log(e+"就是当前的事件对象")
console.log( this+ "就是当前你点击的对象");
alert("我是div的点击事件,所有浏览器中,我的功能都是弹出来这句话!");
}
//通用的
// div.onclick = huidiao;
//ie9以上才支持
// div.addEventListener("click",huidiao)
//ie9(不包括9)以下支持的
// div.attachEvent("onclick",function(){
// huidiao.call(div, window.event);
// })
}
</script>
## 7.正则(JS中的正则对象)的方法
<script>
// 跟正则表达式相关的方法
// 1 RegExp对象
// test() 匹配
// exec() 提取 提取一个内容
// 2 String对象
// match() 提取 可以提取多个内容
// replace() 替换
// split() 切割
// search()
var str = '张三:2500,李四:3000,王五:50000';
// var reg = /\d+/gi; // gi 全局匹配并且忽略大小写
var reg = /\d+/g;
// exec() 只返回一个匹配到的结果 如果没有匹配的内容返回null
// var content = reg.exec(str);
// console.log(content);
// content = reg.exec(str);
// console.log(content);
// content = reg.exec(str);
// console.log(content);
// content = reg.exec(str);
// console.log(content);
do {
var content = reg.exec(str);
// } while(content != null);
if (content) {
console.log(content[0]);
}
} while(content);
</script>
### 1.提取
<script>
// 1. 提取工资
// var str = '张三:1000,李四:5000,王五:8000。';
// var reg = /\d+/g;
// // 提取多个内容
// console.log(str.match(reg));
// console.log(str.match(reg));
// 2. 提取email地址
// var str = '123123@xx.com,fangfang@valuedopinions.cn 这是其它内容 286669312@qq.com 2、emailenglish@emailenglish.englishtown.com 286669312@qq.com...';
// var reg = /\w+@\w+(\.\w+)+/g;
// console.log(str.match(reg));
// 3. 分组提取
// 3. 提取日期中的年部分 2015-5-10
// var dateStr = '2015-1-5';
// var reg = /(\d{4})-(\d{1,2})-(\d{1,2})/;
// // reg.test(dateStr);
// // reg.exec(dateStr);
// // dateStr.match(reg);
// console.log(RegExp.$1);
// console.log(RegExp.$2);
// console.log(RegExp.$3);
// 4. 提取邮件中的每一部分
var str = 'xxxx@itcast.com';
var reg = /(\w+)@(\w+)\.(\w+)/;
reg.test(str);
console.log(RegExp.$1);
console.log(RegExp.$2);
console.log(RegExp.$3);
</script>
### 2.split
<script>
// 1. 提取日期中的年部分 2015-5-10
// var dateStr = '2015-1-5';
// console.log(dateStr.split('-'));
// var dateStr = '2015/1-5';
// console.log(dateStr.split(/[/-]/));
// 2. 提取邮件中的每一部分
var str = 'xxxx@itcast.com';
console.log(str.split(/[@\.]/));
</script>
### 3.替换
<script>
/*// 1. 替换所有空白
var str = " 123AD asadf asadfasf adf ";
// trim() 去除前后的空格
// console.log( str.trim());
// replace() 只能替换掉第一个查找到的内容
// console.log(str.replace(' ', 'x'));
// console.log(str.replace(/\s/g, ''));
// console.log(str.split(' ').join(''));
// 2. 把所有,和,替换为.
var str = "abc,efg,123,abc,123,a";
console.log(str.replace(/,|,/g, '.'));*/
var box = document.getElementById("box")
var str2 = "黑马程序员, 属于传智旗下高端品牌, 黑马程序员涵盖了很多的学科, 前端也是属于黑马程序员的学科中的一员";
var str3 = "黑马程序员"
eval("var regStr = /"+str3+"/g ;")
box.innerHTML = str2.replace(regStr, "<a href='http://www.itheima.com'>"+str3+"</a>")
</script>
</script>