標籤:之間 函數繼承 其他 簡單 htm efi return 並且 apply
1.類和對象的概念:
1.所有的事物都是一個對象,而類就是具有相同屬性和行為方法的事物的集合
2.在JavaScript中建立對象的目的就是將所有的具有相同屬性的行為的代碼整合到一起,方便使用者的管理
3.類是具有相同特徵和方法(行為)的事物的抽象,其中可以理解為:對象是類的執行個體,類是對象的執行個體
2.如何建立一個對象:
var str = "123" ; // string字串var str2 = new String("123"); // object對象
3.建立對象有以下兩種方式:
//第一種方式var obj = new Object();console.log(typeof obj); // object對象//第二種方式var obj1 = {};console.log(typeof obj1); // object對象
4.如何給對象添加屬性和方法
var person1 = { name:"小明", age:20, height:180, sex:"男", walk:function(){ console.log("i can walk!") ; return 2; }}var _name1 = person1.name;console.log(_name1); // 結果為:小明console.log(person1.walk()); // 結果為:i can walk 2在這裡需要注意:在對象中添加的內容:屬性和屬性值用:(冒號)隔開,屬性和屬性之間用;(逗號)隔開,在調用對象的屬性和方法是用.(點)進行調用,尤其在
最後的一個屬性後面不能加,(逗號),系統會報錯
5.如何利用函數的方法給對象添加屬性和方法
var person = function(_name,_age,_height,_sex){ var obj = new Object();//建立一個新的對象 obj.name = _name, obj.age = _age, obj.height = _height, obj.sex = _sex, obj.walk = function(){ console.log("i can walk"); return 2; } return obj; // 將建好的對象需做為函數的傳回值返回}var person = new person("小明",16,160,"男");console.log(person.walk());// 輸出結果:i can walk 2person.walk();//輸出結果:i can walkconsole.log(person.height); // 輸出結果: 160
6.用夠著函數的方法建立對象:注意:建構函式的首字母大寫;建構函式的機制:建構函式會自動建立一個Null 物件,然後與this向關聯,並且作為預設傳回值返回
function Person(_name,_age,_height){ this.name = _name, this.age = _age, this.height = _height, this.walk = function(){ console.log("i can walk"); return 2; }} var person1 = new Person("小明",18,180);var person2 = new Person("小紅",20,170);console.log(person1.name);//輸出結果:小明console.log(person2.walk());// i can walk 2person1.walk();i can walk
注意:建構函式:通過建構函式我們就不用反覆定義屬性和方法,我們通過建構函式構造了兩個對象:person1,person2.同時person1和person2也可以叫做夠著函數Person的兩個執行個體。
7.當然系統內建了許多的建構函式 例如:String Array Object Number:簡單用代碼舉兩個例子
var str1 = new String("123");console.log(str1);//輸出結果:String{“123”}console.log(typeof str1);//輸出結果為:Objectvar str2 = new Number("123");console.log(str2);//輸出結果為:Number{123}console.log(typeof str2);//輸出結果為:object可見他們都是一種建構函式,建立出來的都是對象
8.原型prototype
prototype是用來解決記憶體被過多佔用的問題,每一個函數在建立的時候都會預設的分配一個prototype屬性,建構函式也不例外,同時prototype是一個指標,他指向一個對象,原型prototype的特點,在記憶體中只有一份
function Person(_name,_age,_height){ this.name = _name, this.age = _age, this.height = _height, this.walk = function(){ console.log("我也會走路"); }} Person.prototype.info = function(){ console.log("我的姓名是:"+this.name);}Person.prototype.walk = function(){ console.log("i can walk");}var person = new Person("小明",18,180);console.log(person.name); //輸出結果:小明person.info();//輸出結果:我的姓名是:小明person.walk();//輸出結果:我也會走路這個時候我們將建構函式中的walk方法注釋掉,之後我們在調用walk方法person.walk();//輸出結果為:i can walk由此可知:當對象嘗試調用摸個屬性和方法的時候,會首先去該對象的建構函式中去找,如果在該函數的建構函式沒有的話就會去,改建構函式的原型中去找
9.將原型也作為一個對象
function Person(_name,_age,_height){ this.name = _name, this.age = _age, this.height = _height this.walk = function(){ console.log("我也會走路"); }}Person.prototype = { info:function(){ console.log("我的姓名是:"+this.name); }, walk:function(){ console.log("i can walk"); }}var person = new Person("小紅",18,170);console.log(person.name);//輸出結果:小紅person.info();//我的姓名是:小紅person.walk();//我也會走路和上面沒有什麼差別,就是換了一種建立原型的方法
10.物件導向有三大特徵:封裝、繼承、多態、我們現在就說一下繼承,在繼承中有很多方法,首先說一下call和apply方法(兩種方法基本是一樣的)call和apply方法的根本在於改變this的指向。但是這種方式只能實現建構函式的繼承,但是不能實現原型的繼承
//首先建立一個建構函式function Person(_name,_age,_sex){ this.name = _name; this.age = _age; this.sex = _sex;}//為建構函式建立原型Person.prototype = { info:function(){ console.log("我的名字是:"+this.name); }, walk:function(){ console.log("i can walk"); }}//建立一個建構函式繼承Personfunction Student(_name,_age,_sex,_height){ Person.call(this,_name,_age,_sex);//call方法進行繼承 this.height = _height;}var student = new Student("小明",18,"男",180);var person = new Person("小紅",16,"女");console.log(student.name,student.height);//輸出結果:小明 180console.log(person.name,student.age); // 小紅 18person.info();//輸出結果為: 我的名字是:小紅student.info();//輸出結果為 student.info is not a function//由此可見:Student雖然繼承了Person的建構函式,但是並沒有繼承Person的原型
11.基於之前的代碼我們更改一下Student的繼承方式改成apply看看有什麼效果
//首先建立一個建構函式function Person(_name,_age,_sex){ this.name = _name; this.age = _age; this.sex = _sex;}//為建構函式建立原型Person.prototype = { info:function(){ console.log("我的名字是:"+this.name); }, walk:function(){ console.log("i can walk"); }}//建立一個建構函式繼承Personfunction Student(_name,_age,_sex,_height){ Person.apply(this,[_name,_age,_sex]);//apply方法進行繼承 this.height = _height;}var student = new Student("小明",18,"男",180);var person = new Person("小紅",16,"女");console.log(student.name,student.height);//輸出結果:小明 180console.log(person.name,student.age); // 小紅 18person.info();//輸出結果為: 我的名字是:小紅student.info();//輸出結果為 student.info is not a function//由此可見:Student雖然繼承了Person的建構函式,但是同樣並沒有繼承Person的原型
12.如何讓student繼承person的原型:在原型繼承的問題上可能有人說我們直接把Person的原型賦值給Student的原型不就行了嗎?那我們先來看看這個方法
//首先我們還是粘貼一下前面的代碼//建立一個建構函式function Person(_name,_age,_sex){ this.name = _name; this.age = _age; this.sex = _sex;}//為建構函式建立原型Person.prototype = { info:function(){ console.log("我的名字是:"+this.name); }, walk:function(){ console.log("i can walk"); }}//建立一個建構函式繼承Personfunction Student(_name,_age,_sex,_height){ Person.apply(this,[_name,_age,_sex]);//apply方法進行繼承 this.height = _height;}//將Person的原型賦值給Student的原型Student.prototype = Person.prototype;//為了區別一下兩個原型,我們在給Student原型在加一個方法Student.prototype.high = function(){ console.log("我的身高是:" + this.height) ;}var person = new Person("小紅",16,"女");var student = new Student("小明",18,"男",180);//在這裡我們只看原型的繼承,建構函式的繼承就不多說了person.info();// 輸出的結果:我的名字是:小紅student.info();//輸出的結果:我的名字是:小明student.high();//輸出的結果:我的身高是:180//目前可見:Student繼承了Person原型,而且他自己專屬的原型方法業保持了//但是這個方法也是有很大的弊端,我們執行一下下面的代碼person.high();//輸出的結果:我的身高是:undefined//這就出問題了,正常應該是person.high not a function才對,因為我們並沒有在person原型裡定義high方法,但是這裡卻顯示方法存在,只是沒有
//定義參數//其實原因很簡單,在之前我們說過這裡的原型就像是一個指標,當我們進行賦值後,更改的是指標所指的地址,於是Student和Person的原型都發生了改變
13.那麼我們如何?原型的繼承呢?在原型我們常用的方法就是講Student的原型作為Person類的一個執行個體化對象
//首先我們還是粘貼一下前面的代碼//建立一個建構函式function Person(_name,_age,_sex){ this.name = _name; this.age = _age; this.sex = _sex;}//為建構函式建立原型Person.prototype = { info:function(){ console.log("我的名字是:"+this.name); }, walk:function(){ console.log("i can walk"); }}//建立一個建構函式繼承Personfunction Student(_name,_age,_sex,_height){ Person.apply(this,[_name,_age,_sex]);//apply方法進行繼承 this.height = _height;}//將Student的原型作為Person的一個執行個體化對象Student.prototype = new Person("天天",16,"女");//為了區別一下兩個原型,我們在給Student原型在加一個方法//原型創造函數1Student.prototype.high = function(){ console.log("我的身高是:" + this.height) ;}//原型創造函數2Student.prototype = { high:function(){ console.log("我的身高是:" + this.height) ; }}var person = new Person("小紅",16,"女");var student = new Student("小明",18,"男",180);//在這裡我們只看原型的繼承,建構函式的繼承就不多說了person.info();// 輸出的結果:我的名字是:小紅student.info();//輸出的結果:我的名字是:小明student.high();//輸出的結果:我的身高是:180//目前可見:到這裡是沒有問題的,下面我們依舊測試一下person.high();//輸出的結果:person.high is not a function//可見這個是對的//當然這個也是有一些其他的問題的//在之前我們提到了兩種創造原型的方式;第一種方式是沒有問題的,現在我們看一下第二種(屏蔽第一種)//此時除了絲毫不影響的person.info()不受影響外;後面就會提示:student.info is not a function:這個原因是什麼呢?//其實這個原因很簡單,就是後面的原型把前面的去遠行給覆蓋掉了,所以說在進行繼承後大家還想給繼承者加上其他方法時就按照原型建立函數1來進行就可以了
14:原型鏈:當對象嘗試擷取某一個屬性或者方法時,若該對象的建構函式沒有,回到建構函式的原型函數中去找,如果原型中也沒有那麼就去原型對象的原型去找,最終到達Object.prototype
javascript的對象、類和方法