js的原型鏈以及繼承
阿新 • • 發佈:2018-11-06
1. 先有建構函式,再有的例項物件
2. 建構函式裡面有一個原型物件
3. 原型物件裡面的構造器指向對應的建構函式
4. 例項物件裡面的原型指向建構函式裡面的原型物件
原型鏈:是一種關係,例項物件和原型物件之間的關係,通過__proto __來聯絡的,建構函式本身與例項物件沒什麼聯絡
建構函式裡面的原型物件裡面的原型__proto__指向的是objct,,objct的原型為null
例如:
var divObj = document.getElementById("dv") console.dir(divObj); var divObj = document.getElementById("dv") console.dir(divObj); divObj.__proto__---->HTMLDivElement.prototype的__proto__-----> HTMLDivElement.prototype的__proto__----->Element.prototype的 __proto__----->Node.prototype的__proto__--------> eventTarget.prototype的__proto__---->Object.prototype沒有__proto__, 所以Object.prototype中的__proto__為null
this物件
建構函式中的this是例項物件
嚴格模式:
"use strict";
function f1 () {
console.log(this) ;window
}
f1(); //當加上嚴格模式後f1()呼叫結果為undefined,Window.f1()才對
不加上嚴格模式,不用加Window
原型物件方法中的this也是例項物件
原型的指向改變
當原型物件prototype裡面的指向改變了,那麼原型__proto__指向也改變了 這裡的原型物件的指向相當於C語言中的指標 先改變原型物件的指向,再新增方法,才能訪問當前的方法
這裡就相當於我告訴你錢在我這讓你來拿,但是你來的途中,我說錢不在我這,所以你在我這拿不到錢,而如果先把錢移動的位置告訴你,你就可以直接拿到錢,是一個道理
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <script> function Person (age) { this.age = age; } Person.prototype.study = function () { console.log("學習很重要"); } function Zhu () { } Zhu.prototype = new Person(10); Zhu.prototype.eat = function () {//指向改變後,再給一個新的原型 console.log("豬隻知道吃"); } var zhu = new Zhu(); // var stu = new Person(10); zhu.study(); zhu.eat(); </script> </body> </html>
繼承
真正的面嚮物件語言存在類(class)(特殊的資料型別),js沒有類的概念,不是面向物件的語言,所以js沒有類,但是js可以模擬面向物件的思想程式設計,js中會通過建構函式來模擬類的概念
繼承:首先繼承是一種關係,類與類之間的關係,js中沒有類,但是通過建構函式模擬類,然後通過原型來實現繼承
繼承也是為了資料共享,js中的繼承也是為了實現資料共享
原型作用之一:實現資料共享,節省空間
原型作用之二:為了實現繼承
1,通過建構函式原型物件來繼承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script>
//通過原型繼承 ,雖然能繼承,但是都是一樣的屬性與值
function Person (name,age,sex) {
this.name = name ;
this.age = age ;
this.sex = sex ;
}
Person.prototype.study = function () {
console.log("學習");
}
function Stu (score) {
// this.name = name ;
// this.age = age ;
// this.sex = sex ;
this.score = score;
}
Stu.prototype = new Person("張",17,"男"); //使學生的指向改變成人,那麼人裡面的屬性和方法都能共享
Stu.prototype.study1 = function () {
console.log("學習");
}
var stu = new Stu(100);
var stu1 = new Stu(100);
var stu2 = new Stu(100);
stu.study();
stu1.study();
stu2.study();
console.log(stu.name,stu.sex,stu.age,stu.score);
console.log(stu1.name,stu1.sex,stu1.age,stu1.score);
console.log(stu1.name,stu1.sex,stu1.age,stu1.score);
</script>
</body>
</html>
這個繼承的缺點是所有繼承的屬性,方法都一樣
那麼如何解決這種問題呢,來後接下來講一講下面這種繼承
2,通過建構函式的借用繼承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script>
//借用建構函式繼承 :建構函式名字.call(當前物件,屬性),解決了屬性繼承,並且值不重複,但是方法不能繼承
function Person (name,age,sex) {
this.name = name ;
this.age = age ;
this.sex = sex ;
}
Person.prototype.study = function () {
console.log("學習");
}
function Stu (name,age,sex,score) {
// this.name = name ;
// this.age = age ;
// this.sex = sex ;
Person.call(this,name,age,sex,score);//相當於呼叫Person物件
this.score = score;
}
// Stu.prototype = new Person("張",17,"男");
Stu.prototype.study1 = function () {
console.log("學習");
}
// stu.name = "張";
// stu.sex = "男"; 在這裡重新賦值就可以了,但是太多,而且這樣就沒有傳值的必要性了
// stu.age = "19";
// var stu1 = new Stu(1);
var stu1 = new Stu("張1","男1",119,1100);
// stu1.name = "張1";
// stu1.sex = "男1";
// stu1.age = "20";
// var stu2 = new Stu(1001);
var stu2 = new Stu("張2","男2",129,1200);
// stu2.name = "張2";
// stu2.sex = "男2";
// stu2.age = "21";
// var stu3 = new Stu(1002);
var stu3 = new Stu("張3","男3",139,1300);
// stu3.name = "張3";
// stu3.sex = "男3";
// stu3.age = "22";
console.log(stu1.name,stu1.sex,stu1.age,stu1.score);
console.log(stu2.name,stu2.sex,stu2.age,stu2.score);
console.log(stu3.name,stu3.sex,stu3.age,stu3.score);
stu3.study(); //報錯,方法不能繼承
</script>
</body>
</html>
這種方法雖然解決了屬性值不用,但是缺陷在於其方法不能繼承,呼叫方法,會報錯 ,那麼為了解決不報錯問題,接下來引入
3.組合繼承(原型與借用一起使用)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script>
function Person (name,age,sex) {
this.name = name ;
this.age = age ;
this.sex = sex ;
}
Person.prototype.study = function () {
console.log("學習");
}
function Stu (name,age,sex,score) {
Person.call(this,name,age,sex,score);//相當於呼叫Person物件
this.score = score;
}
Stu.prototype = new Person(); //不傳值
Stu.prototype.study1 = function () {
console.log("學習");
}
var stu1 = new Stu("張1","男1",119,1100);
var stu2 = new Stu("張2","男2",129,1200);
var stu3 = new Stu("張3","男3",139,1300);
console.log(stu1.name,stu1.sex,stu1.age,stu1.score);
stu1.study();
console.log(stu2.name,stu2.sex,stu2.age,stu2.score);
stu2.study();
console.log(stu3.name,stu3.sex,stu3.age,stu3.score);
stu3.study();
</script>
</body>
</html>
後面還有繼承的方法,明日再來總結