C++的四種cast——dynamic_cast
一.建構函式和原型
1、建構函式
1.概述
建構函式是一種特殊的函式,主要用來初始化物件,即為物件成員變數賦初始值,它總與new一起使用,我們可以吧物件中一些公共的屬性和方法抽取出來,然後封裝到這個函式裡面。
new在執行時會做四件事:
-
-
讓this指向這個新的物件;
-
執行建構函式裡面的程式碼,給這個新物件新增屬性和方法;
-
返回這個新物件(所以建構函式裡面不需要return)。
建立物件的三種方式:
1.物件字面量
var obj1={};
-
new Object()
var obj2=new Object();
3.自定義建構函式
function Star(uname,age){
this.uname=name;
this.age=age;
this.sing=function(){
console.log("我會唱歌啊");
}
}
var ldh=new Star('劉德華',42);
var zxy=new Star('張學友',46);
ldh.sing();
zxy.sing();
下文皆使用這個例子來說明。
2.成員
JavaScript的建構函式中可以新增一些成員,可以在建構函式本身新增,也可以在建構函式內部的this上新增。通過這兩種方式新增的成員,就分別為靜態成員
-
靜態成員:在建構函式本身上新增的成員,只能由建構函式本身來訪問;
function Star(uname,age){
this.uname=name;
this.age=age;
this.sing=function(){
console.log("我會唱歌啊");
}
}
Star.sex="男";//在建構函式本身新增 就是靜態成員
console.log(Ster.sex);//只能通過本身來訪問
-
例項成員:在建構函式內部建立的物件成員,只能由例項化的物件來訪問。
function Star(uname,age){ this.uname=name; this.age=age; this.sing=function(){ console.log("我會唱歌啊"); } } var ldh=new Star('劉德華',42); //這裡面的 uname age sing 就是例項成員,都是通過this新增的成員。只能通過例項物件ldh來訪問
2.物件原型prototype
建構函式雖然很好用,但是存在浪費記憶體的問題~
美創造一個都會開闢一個新的空間。
這就來了原型prototype 解決這個問題~
建構函式通過原型分配的函式是所有物件共享的;
JavaScript規定:每一個建構函式都有一個prototype屬性,指向另一個物件。注意這個prototype就是一個物件,這個物件的所有屬性方法,都會被建構函式擁有。
我們把那些不變的方法直接定義在原型物件上,這樣所有的物件的例項就可以共享這些方法,就節約了記憶體空間。
function Star(uname,age){
this.uname=name;
this.age=age;
}
Star.prototype.sing=function(){
console.log("我會唱歌啊");
}//把sing這個方法定義在原型上
var ldh=new Star('劉德華',42);
var zxy=new Star('張學友',46);
ldh.sing();
zxy.sing();
3.原型物件 proto
物件都會有一個屬性proto指向建構函式的prototype原型物件,之所以我們物件可以使用建構函式prototype原型物件的屬性和方法,就是因為物件proto的存在。
-
proto物件原型和原型物件prototype是等價的
console.log(ldh.__proto__ === Star.prototype)//true
-
proto物件原型的意義就在於為物件的查詢機制提供一個路線。但是是一個非標準屬性,在實際開發中,不可以使用這個屬性,他只是內部指向原型物件prototype。
來張圖理解理解~
4. constructor建構函式
物件原型(proto)和原型物件(prototype)都有一個constructor屬性,constructor我們稱為建構函式,因為它指回建構函式本身。
很多情況下,我們需要用constructor函式指回原來的建構函式。
Star.prototype={
constructor:Star,//如果不新增這一步,那麼就會把原來的物件覆蓋,因此不會指向原來的建構函式
Sing:fnction(){
console.log("我會唱歌");
},
Movie:fnction(){
console.log("我會演電影");
}
}
console.log(Star.prototype.constructor);
//指回原來的建構函式
5.三者的關係
6.原型鏈
查詢成員是按照這個原型鏈一層一層找下去,如果沒找到,就返回undifined。
成員查詢規則:
-
當訪問一個物件的屬性時,首先查詢這個物件自身有沒有這個屬性;
-
如果沒有就查詢他的原型也就是proto指向的prototype原型物件;
-
如果也沒有找到,就查詢原型物件的原型(Object的原型物件);
-
依此類推直到找到Object為止(null)。
7.擴充套件內建物件
通過原型物件,對原來的內建物件進行擴充套件自定義的方法。
例子:新增一個加法方法sum
<script>
Array.prototype.sum = function () {
var sum = 0;
for (var i = 0; i < this.length; i++) {
sum += this[i];
}
return sum;
}
var arr = [1, 2, 3];
console.log(arr.sum());
</script>
注意:陣列和字串內建物件不能給原型物件覆蓋操作Array.prototype={},只能是Array.prototype.xxx=function(){}的方式。
二、繼承
ES6之前不提供extends繼承,可以通過建構函式+原型物件模擬實現繼承,被稱為組合繼承。
1.call( )
呼叫這個函式,並且修改函式執行時的this指向。
fun.call(當前呼叫函式this的指向物件,引數1,引數2,...)
function myFunction(a, b) {
return a * b;
}
myObject = myFunction.call(myObject, 10, 2); // 返回 20
2.借用父建構函式繼承屬性
例子:
<script>
function Father(uname, age) {
this.uname = name;
this.age = age;
}
function Son(uname, age) {
Father.call(this, uname, age);
}
var son = new Son('劉德華', 34);
console.log(son);//添加了這兩個屬性
</script>
2.借用原型物件繼承屬性
<script>
function Father(uname, age) {
this.uname = name;
this.age = age;
}
Father.prototype.money = function () {
console.log('賺了10000塊');
}
Son.prototype = new Father();
//用了物件的形式秀髮i了原型物件用constructor指回原來的建構函式
Son.prototype.constructor = Son;
function Son(uname, age, score) {
Father.call(this, uname, age);
this.score = score;
}
var son = new Son('劉德華', 34, 100);
console.log(son);
console.log(Son.prototype.constructor);
</script>
圖片分析過程:
在Father原型物件上添加了money這個方法,當Son要使用這個方法時,建立一個Father例項物件,Son原型物件指向這個例項物件,這個例項物件裡面有一個proto物件原型指向Father原型物件,也就相當於繼承到了這個方法。
本文為pink老師視訊的筆記,原視訊指路: