構造函數(shù)繼承
- 繼承:子類繼承父類所有屬性和行為,父類不受影響。
- 目的:找到類之間的共性精簡代碼
//構造函數(shù)繼承只能繼承對象內(nèi)部方法
function Person(name){
this.name = name;
this.eyes = "兩只";
this.legs = "兩條";
}
function Student(name){
Person.call(this,name);
// Person.apply(this,[name]);
// Person.bind(this)(name);
this.className = "二班";
}
let newPerson = new Student("張三");
console.log(newPerson.className);
為了實現(xiàn)原型的繼承可以使用原型的賦值
- 但是簡單原型繼承,出現(xiàn)影響父類的情況;
function Dad(height){
this.name = "張三";
this.age = 20;
this.height = height;
this.money = "$1000000";
}
Dad.prototype.hobby = function(){
console.log("喜歡高爾夫");
}
function Son(height){
Dad.call(this,height);
// Dad.apply(this,[height])
// Dad.bind(this)(height);
}
Son.prototype = Dad.prototype //直接賦值
Son.prototype.hobby = function(){
console.log("籃球");
}
let newSon = new Son("178cm");
// console.log(newSon);
newSon.hobby(); // 籃球
let newDad = new Dad("179cm");
newDad.hobby(); //籃球
//輸出兩個都是顯示籃球,父類方法被覆蓋了繼承方法不可靠
- 組合繼承 修改子類原型的指向,添加一個構造函數(shù)做為媒介
function Dad(){
this.name = "張三";
}
Dad.prototype.hobby = function(){
console.log("高爾夫");
}
function Son(){
Dad.call(this);
}
let F = function(){}
F.prototype = Dad.prototype;
Son.prototype = new F(); // 新開辟內(nèi)存地址
Son.prototype.constructor = Son;
Son.prototype.hobby = function(){
console.log("籃球");
};
let newSon = new Son("178cm");
// console.log(newSon);
newSon.hobby(); // 籃球
let newDad = new Dad("179cm");
newDad.hobby(); //高爾夫
原型的深拷貝繼承
-
傳值和傳址問題
- 基本數(shù)據(jù)類型:Number、String、Boolean、Null、Undefined 拷貝不存在傳值問題
- 復雜數(shù)據(jù)類型/引用數(shù)據(jù)類型:Array、Date、Math、RegExp、Object、Function等存在拷貝傳值問題
let a = 10;
let b = a;
b = 20;
console.log(a); // 10 b 改版沒有影響a 的值
let obj = {
name: "張三",
age: 20,
arr: [1, 2, 3],
obj3: {
},
test: undefined,
fn: function () {
console.log("fn...");
},
test2: null
}
let obj2 = obj;
obj2.age = 30;
console.log(obj); /*{name: "張三", age: 30, arr: Array(3), obj3: {…}, test: undefined, …}
age: 30
arr: (3) [1, 2, 3]
fn: ? ()
name: "張三"
obj3: {}
test: undefined
test2: null
__proto__: Object*/
// 結果顯示obj 屬性age被修改了
- 采用JSON序列化拷貝對象
let obj2 = JSON.parse(JSON.stringify(obj));
obj2.age = 30;
console.log(obj2);
/*{name: "張三", age: 30, arr: Array(3), obj3: {…}, test2: null}
age: 30
arr: (3) [1, 2, 3]
name: "張三"
obj3: {}
test2: null
__proto__: Object*/
console.log(obj); /* {name: "張三", age: 20, arr: Array(3), obj3: {…}, test: undefined, …}
age: 20
arr: (3) [1, 2, 3]
fn: ? ()
name: "張三"
obj3: {}
test: undefined
test2: null
__proto__: Object*/
-JOSN序列化的不足
如果拷貝對象包含函數(shù),或者undefined等值,此方法就會出現(xiàn)問題
- 淺拷貝和深拷貝
//遞歸深拷貝
function deepCopy(obj){
let newObj = Array.isArray(obj)?[]:{};
for(let key in obj){
if(obj.hasOwnProperty(key)){
if(typeof obj[key] == "object"){
newObj[key] = deepCopy(obj[key]);
}else{
newObj[key] = obj[key];
}
}
}
return newObj;
}
let obj2 = deepCopy(obj);
console.log(obj2);/*{name: "張三", age: 20, arr: Array(3), obj3: {…}, test: undefined, …}
age: 20
arr: (3) [1, 2, 3]
fn: ? ()
name: "張三"
obj3: {}
test: undefined
test2: null
__proto__: Object*/拷貝成功
- 深拷貝繼承
function Dad(){
this.name = "張三";
}
Dad.prototype.hobby = function(){
console.log("高爾夫");
}
function Son(){
Dad.call(this);
}
Son.prototype = deepCopy(Dad.prototype); // 新開辟內(nèi)存地址
Son.prototype.constructor = Son;
Son.prototype.hobby = function(){
console.log("籃球");
};
let newSon = new Son("178cm");
newSon.hobby(); // 籃球
let newDad = new Dad("179cm");
newDad.hobby(); //高爾夫
原型的繼承
- 原型鏈是指對象在訪問屬性或方法時的查找方式。
1.當訪問一個對象的屬性或方法時,會先在對象自身上查找屬性或方法是否存在,如果存在就使用對象自身的屬性或方法。如果不存在就去創(chuàng)建對象的構造函數(shù)的原型對象中查找 ,依此類推,直到找到為止。如果到頂層對象中還找不到,則返回 undefined。
2.原型鏈最頂層為 Object 構造函數(shù)的 prototype 原型對象,給 Object.prototype 添加屬性或方法可以被除 null 和 undefined 之外的所有數(shù)據(jù)類型對象使用。
function Drag(){
this.ele = "some value..."
}
Drag.prototype.ele = "prototype value....";
let drag1 = new Drag();
console.log(drag1.ele); // 輸出some value...
function Drag(){
// this.ele = "some value..."
}
Drag.prototype.ele = "prototype value....";
let drag1 = new Drag();
console.log(drag1.ele); // 輸出 prototype value....
function Drag(){
// this.ele = "some value..."
}
// Drag.prototype.ele = "prototype value....";
Object.prototype.ele = 'Object.value...';
let drag1 = new Drag();
console.log(drag1.ele); // 輸出 Object.value...
ES6中的類
- 類的寫法
class Person{
height="178cm";
constructor(name,age){
//屬性
this.name = name;
this.age = age;
}
//方法
getName(){
console.log("姓名是:"+this.name);
}
}
let student = new Person("張三",20);
student.getName();
-
靜態(tài)方法和屬性:實例不會繼承的屬性和方法
class Person{ //靜態(tài)方法 static hobby(){ console.log("喜歡籃球"); } } //靜態(tài)屬性 Person.height = "178cm"; //通過類來調(diào)用 Person.hobby(); console.log(Person.height);
-
類的繼承:extends
class Dad{ name = "張三"; age = 40; constructor(height){ this.height = height; } hobby(){ console.log("喜歡籃球"); } } class Son extends Dad{ constructor(height){ //表示父類的構造函數(shù) super(height); } } let son1 = new Son("178cm"); son1.hobby(); console.log(son1.height);
包裝對象
- 除過null,undefined,基本類型都有自己對應的包裝對象:String Number Boolean
- 包裝對象把所有的屬性和方法給了基本類型,然后包裝對象消失
常用方法
- hasOwnProperty():看是不是對象自身底下的屬性
- contructor查看對象的構造函數(shù) 可以用來做判斷
- instanceof:對象與構造函數(shù)是否在原型鏈上有關系
- toString()判斷類型; 轉(zhuǎn)換字符串 進制轉(zhuǎn)換