JavaScript面相對象的繼承
一.in操作符與hasOwnProperty的用法和區(qū)別
in操作符:
①遍歷對象
②判斷(檢查)對象中是否存在指定的屬性(實例成員 + 原型成員)
語法:'屬性' in 對象
hasOwnProperty:
檢查對象是否擁有這個屬性(只檢查自己的成員,實例成員)
語法:對象.hasOwnProperty(屬性|方法);
<script>
//1.創(chuàng)建一個空對象
var o = {};
//2.提供一個已經(jīng)有的對象obj
var obj = {
name:'對象的屬性',
age:20,
demo:{nme:"lalala"},
sayHello:function (){
console.log('hello');
}
};
//3.混入式繼承(把原有對象的所有屬性和方法都拷貝給新的對象)
for (var k in obj){
if(obj.hasOwnProperty(k)) {
o[k] = obj[k];
}
}
//注意:利用for...in賦值和直接賦值不一樣,for...in賦值只有引用類型的屬共享,其他的值類型不共享,
//直接賦值的話,直接賦值:完全共享.賦值的是地址指針,所得屬性都是共享的.
//4,打印查看o對象
console.log(o.des);
console.log(o);//object
console.log(obj.des);//undefined
obj.sayHello = function (){
console.log('改變了');
};
//5.問題:新對象的引用類型屬性和舊對象中的對應(yīng)屬性是否相等
console.log(o.sayHello == obj.sayHello,"___");//true
console.log(o.sayHello == obj.sayHello);//false
//注意:在修改方法的時候,這里的方法是使用函數(shù)聲明了.重新設(shè)置了一個聲明的函數(shù),重新定義了一個函數(shù)的地址空間,所以這里的函數(shù)方法不是共存的所以方法不相等.
console.log(o.sayHello);
console.log(obj.sayHello);
//問題:那么兩個對象中的其中某個修改了該屬性,則另一個對象會受到影響
console.log(o.demo == obj.demo);
o.demo.nme = "nnnn";
console.log(o.demo == obj.demo);
</script>
補充說明:
eg:<script>
function Person(){
this.name = "默認(rèn)"
}
Person.prototype.hi = "hi";
var p1 = new Person();
var o = {};
/*for (var k in p1)
{
if(p1.hasOwnProperty(k))
{
o[k] = p1[k];
}
}
console.log(o.hi);*/
</script>
<script>
var obj = {
name:"123",
showName:function(){
console.log("12345");
}
}
/* var obj2 = obj;*/
var obj2 = {};
//直接賦值:完全共享
/* obj.name = "sss";
console.log(obj2.name);*/
for(var k in obj){
if(obj.hasOwnProperty(k)){
obj2[k] = obj[k];
}
}
console.log(obj.showName == obj2.showName);//true
obj.showName = function (){
console.log('改變了');
}
console.log(obj.showName == obj2.showName);
</script>
圖形解析:
(1)
(2)
(3)
二.原型對象的補充說明
1.構(gòu)造函數(shù)有一個相關(guān)聯(lián)的原型對象,這個原型對象默認(rèn)是一個空對象{}(實際上這個原型對象擁有一個屬性為constructor屬性的對象).
2.構(gòu)造函數(shù)的原型對象本身是一個Object類型的,Person.prototype (原型對象)是Object,他的構(gòu)造函數(shù)是Object
3.使用構(gòu)造函數(shù)創(chuàng)建出來的對象會擁有一個構(gòu)造器屬性(constructor),該屬性指向創(chuàng)建當(dāng)前對象的構(gòu)造函數(shù).
4.對象本身沒有構(gòu)造器屬性,這個屬性是從原型對象上繼承來的.
eg:
<script>
function Person(){
}
var p1 = Person();
// console.log(p1.constructor == Person);//報錯
console.log(Person.prototype.constructor == Person);//true
</script>
console.log(Person.prototype);//Object
var o = {};
console.log(o);
console.log(Person.prototype.constructor);//Person這個對象的(訪問的是自己的實例屬性)
delete Person.prototype.constructor;
console.log(Person.prototype.constructor);//Object這個對象的(訪問的是原型對象上面的屬性)
問題???
構(gòu)造函數(shù)的原型對象(空對象|Object類型),他的構(gòu)造函數(shù)是Object,那么他的構(gòu)造器屬性難道不應(yīng)該是Object嗎?
解答:
構(gòu)造器的原型對象身上其實有兩個(constructor)屬性(實例屬性 + 構(gòu)造函數(shù)的原型對象的原型對象上面的屬性)
圖形解析:
三.繼承的幾種實現(xiàn)方案
- 屬性拷貝(淺拷貝)
- 原型式繼承(A.B.C)
- 原型鏈繼承
- 借用構(gòu)造函數(shù)
- 組合繼承
- (深拷貝 + 原型式)組合繼承
知識點1:屬性拷貝和直接賦值的區(qū)別:
01 屬性拷貝:
引用類型: (數(shù)組):引用會共享,如果重新設(shè)置,那么會切斷聯(lián)系
引用類型:(函數(shù)):函數(shù)會共享,如果重新設(shè)置,那么會切斷聯(lián)系.
==注意==
屬性拷貝的包括成員和原型對象
02 直接賦值:
直接賦值:完全共享!
數(shù)組: 數(shù)組會共享,如果重新設(shè)置,那么另一個對象會受影響.
函數(shù): 函數(shù)會共享,如果重新設(shè)置,那么另一個對象會受影響.
==1.屬性拷貝繼承:==
eg1:
<script>
var obj1 = {
arr :[1,2,3],
show:function (){
console.log('show');
}
}
var o = {};
//屬性拷貝
for(var i in obj1){
o[i] = obj1[i];
}
console.log(o);
console.log(o.arr);
console.log(obj1.arr);
//重新設(shè)置值
obj1.arr = ['demo1','demo2'];
console.log(o.arr);
console.log(obj1.arr);//受影響
</script>
eg2:
<script>
function Person(){
this.name = '默認(rèn)的名稱';
this.friends = ['123','456','789'];
}
Person.prototype.hi = 'hi';
var p1 = new Person();
var o = {};
//屬性拷貝
for(var k in p1){
if(p1.hasOwnProperty(k)){//排除了拷貝原型對象
o[k] = p1[k];
}
}
console.log(o);
console.log(p1);
o.name = '我是一個數(shù)字';
console.log(p1.name);//默認(rèn)名稱
p1.friends.push('我給改變了');
console.log(o.friends);
console.log(p1.hi);
console.log(o.hi);//undefined
</script>
圖像解析1:
圖形解析2:
==直接賦值拷貝==
eg1:
<script>
var demo1 = {
arr:[1,2,3],
show:function (){
console.log('show');
}
};
//直接賦值
var demo2 = demo1;
console.log(demo1.arr);
console.log(demo2.arr);
demo1.arr = ['test1','test2'];
console.log(demo1.arr);
console.log(demo2.arr);
demo1.show();
demo2.show();
demo1.show = function (){
console.log('hahaha');
}
demo1.show();
demo2.show();
</script>
圖形解析:
==2.原型式繼承==
A 利用對象的動態(tài)特性 (對象-原型)
B 字面量直接替換 (對象-原型)
C 設(shè)置子構(gòu)造函數(shù)的原型對象 = 父構(gòu)造函數(shù)的原型對象 (子構(gòu)造函數(shù)-父構(gòu)造函數(shù))
問題:可以獲得父構(gòu)造函數(shù)原型對象上面的屬性和方法,但是無法獲得父構(gòu)造函數(shù)的實例對象上的屬性和方法.
eg:
A 利用對象的動態(tài)特性 對象-原型
<script>
function Person (name){
this.name = name;
}
Person.prototype.des = '描述信息';
var p1 = new Person('張三');
</script>
B 字面量直接替換 對象-原型
<script>
function Person(name){
this.name = name;
}
Person.prototype = {
constructor:Person,
des:'默認(rèn)的描述信息'
}
var p1 = new Person('張三');
</script>
C 設(shè)置子構(gòu)造函數(shù)的原型對象=父構(gòu)造函數(shù)的原型對象 子構(gòu)造函數(shù)-父構(gòu)造函數(shù)
<script>
function Person(){
this.name = '張三';
}
Person.prototype = {
constructor:Person,
des:'默認(rèn)的描述信息',
showDes:function (){
console.log(this.des);
}
}
function Boy() {
this.lol = function (){
console.log('lol');
}
}
//設(shè)置子構(gòu)造函數(shù)的原型對象為父構(gòu)造函數(shù)的原型對象,便可以繼承父構(gòu)造函數(shù)的原型對象的屬性和方法
Boy.prototype = Person.prototype;
var boy1 = new Boy();
console.log(boy1.des);//默認(rèn)描述信息
boy1.showDes();
boy1.lol();
</script>
圖形解析:
==3.擴展內(nèi)置對象==
定義:
把需要共享的屬性和方法寫在內(nèi)置構(gòu)造函數(shù)的原型對象上.
問題:
01 原型對象上面所有的屬性和方法都會被該構(gòu)造函數(shù)創(chuàng)建出來的對象共享,共享可能會導(dǎo)致一些問題.
02 如果所有的開發(fā)人員都往內(nèi)置構(gòu)造函數(shù)的原型對象上面添加屬性和方法,那么原型上面的屬性和方法會越來越多,難以管理,難以維護,還可能會出現(xiàn)覆蓋問題.
eg:
<script>
//需求:要求給arr1添加屬性name|desLog
var arr1 = [1,2,3];
console.log(arr1);//arr1的構(gòu)造函數(shù)為Array
console.log(arr1.constructor);
arr1.name = 'arr1的名稱';
arr1.desLog = function (){
console.log('arr1的des');
};
console.log(arr1);
//需求:要求給arr2添加屬性name|desLog
var arr2 = ['demo1','demo2'];
arr2.name = 'arr2的名稱';
arr2.desLog = function (){
console.log('arr2的des');
}
console.log(arr2);
//需求:要求所有的數(shù)組都擁有name和desLog方法养筒?
</script>
<script>
Array.prototype.name = '默認(rèn)的名稱';
Array.prototype.desLog = function (){
console.log('默認(rèn)的描述信息');
}
var arr1 = [1];
var arr2 = ['demo1'];
console.log(arr1.name);
console.log(arr2.name);
arr1.desLog();
arr2.desLog();
</script>
注意:共享可能會導(dǎo)致一些問題如下
<script>
Array.prototype.name = 'name';
var arr1 = [1,2,3,4];
for (var i = 0;i<arr1.length;i++){
console.log(i,arr1[i]);
}
console.log('---------------');
for(var i in arr1){
console.log(i,arr1[i]);//會打印出name name
}
//兩次遍歷打印的結(jié)果不一樣
</script>
安全的擴展內(nèi)置對象:
01 提供一個自定義的構(gòu)造函數(shù)(空函數(shù))(MyArray)
02 設(shè)置該構(gòu)造函數(shù)的原型對象為內(nèi)置構(gòu)造函數(shù)的實例
03 在構(gòu)造函數(shù)的原型對象上面添加屬性和方法
04 使用自定義的構(gòu)造函數(shù)來創(chuàng)建對象并且使用
eg:
<script>
//1.提供一個自定義的構(gòu)造函數(shù)
function MyArray(){}
//2.設(shè)置該構(gòu)造函數(shù)的原型對象為內(nèi)置構(gòu)造函數(shù)的一個實例
MyArray.prototype = new Array();//獲得Array的所有的屬性和方法
//MyArray.prototype = Array.prototype;
//3.設(shè)置原型對象
MyArray.prototype.name = '默認(rèn)名稱';
MyArray.prototype.desLog = function (){
console.log('哈哈');
}
//4.使用自定義的構(gòu)造函數(shù)來創(chuàng)建對象并且使用
var myArr01 = new MyArray();
myArr01.push('123','345');
console.log(myArr01);
console.log(myArr01.name);//默認(rèn)名稱
myArr01.desLog();//哈哈
var myArr02 = new MyArray();
console.log(myArr02);
//其他的開發(fā)人員
function OtherArray (){};
OtherArray.prototype = new Array();
OtherArray.prototype.name = '默認(rèn)名稱++++++++++++';
OtherArray.prototype.desLog = function (){
console.log('嘿嘿');
}
var other1 = new OtherArray();
other1.push('demo1','demo2');
console.log(other1);
console.log(other1.name);
var arr = new MyArray();
console.log(arr.name);//默認(rèn)名稱
</script>
圖形解析:
原型鏈的結(jié)構(gòu)
- 其實在js中所有的對象都是由構(gòu)造函數(shù)創(chuàng)建出來的
- 所有的構(gòu)造函數(shù)的原型對象所有一個相關(guān)聯(lián)的原型對象
- 所有構(gòu)造函數(shù)的原型對象本身也是一個對象,所以構(gòu)造函數(shù)的原型對象也是由構(gòu)造函數(shù)創(chuàng)建出來的
- 構(gòu)造函數(shù)的原型對象的構(gòu)造函數(shù)也有一個與之相關(guān)聯(lián)的原型對象,這個原型對象本身也是一個對象
- 構(gòu)造函數(shù)的原型對象的原型對象也有自己的構(gòu)造函數(shù)
- 構(gòu)造函數(shù)的原型對象的原型對象也有自己的原型對象.以上會形成一種鏈?zhǔn)浇Y(jié)構(gòu),這個結(jié)構(gòu)就是原型鏈.
- 在原型鏈的頂端(終點)Object.prototype
- Object.prototype本身也是一個對象,所以也有自己的構(gòu)造函數(shù)===>Object
- Object.prototype的原型對象應(yīng)該是它的構(gòu)造函數(shù)的原型對象 Object.prototype (推理 不成立)
Object.prototype.__proto__=Object .prototype.constructor.prototype[Object.prototype]
- js處理:Object.prototype.__proto__ = null;
圖形解析:
image
原型鏈中屬性的搜索規(guī)則:
對象在訪問屬性的屬性的時候,首先先查找實例對象的成員(屬性|方法)
如果找到了,那么就直接使用,如果沒有找到,那么就去它的原型對象上面查找,如果找到了就直接使用.
如果原型上面也沒有找到,那么就繼續(xù)搜索原型對象的原型對象,如果找到了就繼續(xù)使用,如果沒有找到,那么就繼續(xù)上面的過程.
...重復(fù)上面的搜索過程
-
如果查找到Object.prototype也沒有找到,那么句undefined或者是報錯.
eg: <script> function Person(){ this.name = '默認(rèn)' } Person.prototype.name = '原型上面的名稱'; Person.prototype.age = '原型上面的年齡'; function Boy(){ this.lol = 'lol'; this.name = '男孩'; } Boy.prototype = new Person(); var boy = new Boy(); console.log(boy.name);//男孩 console.log(boy.age);//原型上面的年齡 console.log(boy.des);//undefined </script>
==4.原型鏈繼承==
形式: 子構(gòu)造函數(shù).prototype = new 父構(gòu)造函數(shù)();
步驟:
提供構(gòu)造函數(shù)
設(shè)置屬性和方法
設(shè)置繼承(原型鏈繼承)
-
修正構(gòu)造器屬性
eg: <script> function A(){ this.a = 'a'; } A.prototype.desA = 'desA'; function B(){ this.b = 'b'; } //設(shè)置原型鏈繼承 B.prototype = new A(); var b = new B(); console.log(b.a); console.log(b.desA); </script>
使用注意點:
- 在設(shè)置完原型鏈接繼承之后,要修正構(gòu)造函數(shù)的原型對象的構(gòu)造器屬性
- 設(shè)置原型對象的屬性和方法這個操作需要注意位置,建議在完成原型鏈繼承之后再添加成員(屬性和方法)
- 在設(shè)置完原型鏈繼承之后,不能使用字面量的方式來替換當(dāng)前構(gòu)造函數(shù)的原型對象(如果替換,繼承結(jié)構(gòu)會丟失)
不足:
01 無法向父構(gòu)造函數(shù)傳遞參數(shù)
02 父構(gòu)造函數(shù)的實例屬性變成了子構(gòu)造函數(shù)創(chuàng)建出來的對象的原型屬性
eg:
<script>
function Person(name){
this.name = name;
this.friends = ['小花','嘩啦','巴拉']
}
Person.prototype.hi = 'hi';
function Boy(){}
//設(shè)置原型鏈繼承
Boy.prototype = new Person('張三');
Boy.prototype.constructor = Boy;
var boy = new Boy();
console.log(boy);
var boy2 = new Boy();
console.log(boy2);
console.log(boy.friends);//?
console.log(boy2.friends);//?
boy.friends.push('taotao');
console.log(boy.friends);
console.log(boy2.friends);
</script>
==5.Object.create的方法說明:==
Object是內(nèi)置構(gòu)造函數(shù)
Object.Create()靜態(tài)方法(直接添加在構(gòu)造函數(shù)上面的方法)
作用:創(chuàng)建對象,并且指向原型對象
-
注意點:該方法是ES5推出,所以有兼容性問題
eg: <script> var obj = { name:'張三' } /* var o = {}; o.__proto__ = obj; console.log(o.name);*/ var o = Object.create(obj);//創(chuàng)建一個對象,并且指定這個對象的原型對象為obj console.log(o); </script>
兼容性處理:
1.先判斷是否支持create方法,如果不支持,那么我們就是要臨時的構(gòu)造函數(shù)來設(shè)置原型對象并創(chuàng)建對象的實例
2.先判斷是否支持,如果不支持,那么我們就為Object主動地提供create方法
3.抽取一個函數(shù),把設(shè)置原型的過程封裝起來
eg:
<script>
var demo = {
name:'demo'
}
if(typeof Object.create == 'function'){
var o = Object.create(demo);
}else{
//var o = {};
//o.__proto__ = demo; //不推薦這樣寫 換一種寫法
//設(shè)置原型對象
//訪問原型對象的幾種方法
//01 構(gòu)造函數(shù).prototype
//02 對象.__proto__
//03 Object.getPrototypeOf
function F(){}
F.prototype = demo;
var o = new F();
}
</script>
<script>
var demo = {
name:'demo'
}
if(typeof Object.create == 'function'){
var o = Object.create(demo);
}else{
Object.create = function (){
function F(){}
F.prototype = demo;
var o = new F();
}
}
</script>
<script>
function Create(obj){
if(typeof Object.create == 'function'){
var o = Object.create(obj);
}else{
function F(){}
F.prototype = obj;
return new F();
}
}
var obj = {age:23};
var o = Create(obj);
</script>
==6.Object.assign()方法==
作用: 拷貝多個對象的屬性(不會拷貝對象的原型成員)而利用for...in...拷貝會拷貝原型成員
語法:Object.assign(目標(biāo)對象,要拷貝的對象...);
eg:
<script>
var obj1 = {
name:'默認(rèn)的名稱'
}
var obj2 = {
age:23
}
var obj3 = {
book:'小說'
}
var obj = {};
Object.assign(obj,obj1,obj2,obj3);
console.log(obj);
</script>
<script>
function Person (){
this.name = '張三'
}
Person.prototype.hi = 'hi';
var p1 = new Person();
var o = {};
Object.assign(o,p1);
console.log(o);
console.log(o.hi);//undefined
</script>
==7.call和apply的用法說明==
call和apply是js中所有對象都擁有的兩種方法
作用:借用對象的方法
call和apply的作用一模一樣
區(qū)別:傳遞參數(shù)不一樣
call:
第一個參數(shù):誰調(diào)用(借用)就傳遞誰,傳遞的是誰,那么函數(shù)內(nèi)部的this就指向誰
其他參數(shù):參數(shù)列表的方式傳遞
對象.方法.call(this綁定的對象,參數(shù)1葱轩,參數(shù)2闸盔,參數(shù)3,...)
apply:
第一個參數(shù):誰調(diào)用(借用)就傳遞誰预麸,傳遞的是誰盖溺,那么函數(shù)內(nèi)部的this就指向誰
其他參數(shù):數(shù)組元素
對象.方法.apply(this綁定的對象,[參數(shù)1砰苍,參數(shù)2莫鸭,參數(shù)3,...])
eg:
<script>
var obj1 = {
name:'張三',
showName:function (param1,param2){
console.log(this.name + param1 + param2);
}
}
var obj2 = {
name:'李四'
}
/*obj1.showName();
obj2.showName();*///obj2要使用obj1的showName方法
obj1.showName.call(obj2,'demo1','demo2');
//obj1.showName.apply(obj2);
obj1.showName.apply(obj2,['demo1','demo2']);
</script>
==8.this.的指向說明詳解:==
this 指向的永遠(yuǎn)都是一個對象(在非嚴(yán)格模式下)
函數(shù)的調(diào)用
01 以普通函數(shù)方式調(diào)用 this -->window
02 以對象的方法來調(diào)用 this --->對象
03 new 構(gòu)造函數(shù)的方式來調(diào)用 this--->指向內(nèi)部新創(chuàng)建的對象
-
04 函數(shù)上下文的方式來調(diào)用(call|apply) this--->綁定的第一個參數(shù) 如果不傳遞參數(shù)那么默認(rèn)指向window
eg: <script> function func(){ console.log(this); } //1.以普通函數(shù)調(diào)用 func();//window var obj = {name:'test'}; obj.funcTest = func; //2.以對象的方法來調(diào)用 obj.funcTest();//obj var o = { test:function (){ console.log(this); } } o.test.call();//window </script>
==9.借用構(gòu)造函數(shù)繼承的基本寫法.==
借用構(gòu)造函數(shù)繼承的基本寫法:
通過借用父構(gòu)造函數(shù)獲得父構(gòu)造函數(shù)的實例屬性
思考:無法獲得父構(gòu)造函數(shù)的原型成員
eg:
<script>
function Person(name){
this.name = name;
}
Person.prototype.hi = 'hi';
function Boy(name,lol){
//在構(gòu)造函數(shù)內(nèi)部默認(rèn)會創(chuàng)建空對象并且賦值給this
this.lol = lol;
//獲取Person構(gòu)造函數(shù)的實例屬性
Person.call(this,name);
}
var boy = new Boy('張三','英雄聯(lián)盟');
console.log(boy.name);
var boy2 = new Boy('李四','CF');
console.log(boy2.name);
console.log(boy.lol);
console.log(boy2.lol);
console.log(boy.hi);//undefined
console.log(boy2.hi);//undefined
</script>
組合構(gòu)造函數(shù)繼承的基本寫法:
eg:
<script>
function Person(name){
this.name = name;
}
Person.prototype.hi = 'hi';
function Boy(name,lol){
//在構(gòu)造函數(shù)內(nèi)部默認(rèn)會創(chuàng)建空對象并且賦值給this
this.lol = lol;
//獲取Person構(gòu)造函數(shù)的實例屬性
Person.call(this,name);
}
//設(shè)置原型鏈繼承
Boy.prototype = Person.prototype;//原型式繼承C(繼承原型對象)
var boy = new Boy('張三','英雄聯(lián)盟');
console.log(boy.name);
var boy2 = new Boy('李四','CF');
console.log(boy2.name);
console.log(boy.lol);
console.log(boy2.lol);
console.log(boy.hi);//hi
console.log(boy2.hi);//hi
console.log(boy);
</script>
==10.深拷貝和淺拷貝:==
淺拷貝:for...in obj[k] = obj1[k] 引用類型會分享
深拷貝:對淺拷貝的方式進行改進
eg:
<script>
var o = {
name:'張三',
friends:['demo1','demo2'],
car:{
type:'奔馳'
}
}
function deepCopy(obj1,obj2){
obj1 = obj1 || {};
for(var k in obj2){
if(obj2.hasOwnProperty(k)){
//判斷是值類型還是引用類型
if(typeof obj2[k] == 'object'){
//如果是引用類型闹丐,那么就再次循環(huán)
//注意:obj1[k]要做初始化處理 ES5
obj1[k] = Array.isArray(obj2[k]?[]:{}); //檢查是什么類型的?如果是數(shù)組[],如果是對象{}
deepCopy(obj1[k],obj2[k]);
}else{
obj1[k] = obj2[k];//值類型
}
}
}
}
var demo = {};
deepCopy(demo,o);
console.log(demo);
demo.car.type = '奧迪';
console.log(o.car.type);
console.log(o);
console.log(demo);
</script>
==11.深拷貝與借用構(gòu)造函數(shù)實現(xiàn)繼承==
01 通過借用父構(gòu)造函數(shù)獲得父構(gòu)造函數(shù)的 實例屬性
02 思考:無法獲得父構(gòu)造函數(shù)的原型成員
eg:
<script>
function deepCopy(obj1,obj2) {
obj1 = obj1 || {};
for(var k in obj2)
{
if (obj2.hasOwnProperty(k)){
//判斷是值類型還是引用類型
if (typeof obj2[k] == "object")
{
//如果是引用類型被因,那么就再次循環(huán)
//注意:obj1[k]要做初始化處理 ES5
obj1[k] = Array.isArray(obj2[k])?[]:{}; //檢查是什么類型的卿拴?如果是數(shù)組[],如果是對象{}
deepCopy(obj1[k],obj2[k]);
}else
{
obj1[k] = obj2[k]; //值類型
}
}
}
}
function Person(name){
this.name = name;
}
Person.prototype.hi = 'hi';
Person.prototype.car = {
type:'飛船'
}
function Boy(name,lol){
//在構(gòu)造函數(shù)內(nèi)部默認(rèn)會創(chuàng)建空對象并且賦值給this
this.lol = lol;
//獲取Person構(gòu)造函數(shù)中的實例屬性
Person.call(this,name);
}
//設(shè)置原型鏈繼承
//Boy.prototype = new Person();
//Boy.prototype = Person.prototype; //原型式繼承C
deepCopy(Boy.prototype,Person.prototype);
var p1 = new Person();
var boy = new Boy('李四','CF');
console.log(p1.car);//飛船
console.log(boy.car);//飛船
p1.car.type = '傻逼了';
console.log(p1.car);//傻逼了
console.log(boy.car);//傻逼了
</script>