## 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;
// }
// }
//使用更好的方式,避免了屢次的判斷
//這裏存在問題就是
//咱們使用統一的方式,進行事件註冊
//一、註冊的事件的處理函數中的,this指向不一致
//使用addEventListener的方式註冊的點擊事件的回調函數中的this 指向target
//可是使用attachEvent的方式註冊點擊事件的回調函數中的this 指向window
//二、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 二、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>