JS面向對象(3) -- Object類,靜態屬性,閉包,私有屬性, call和apply的使用,繼承的三種實現方法

相關連接:javascript

JS面向對象(1) -- 簡介,入門,系統經常使用類,自定義類,constructor,typeof,instanceof,對象在內存中的表現形式html

JS面向對象(2) -- this的使用,對象之間的賦值,for...in語句,delete使用,成員方法,json對象的使用,prototype的使用,原型繼承與原型鏈java

JS面向對象(3) -- Object類,靜態屬性,閉包,私有屬性, call和apply的使用,繼承的三種實現方法json

1.Object類數組

在JS中,Object是全部類的基類,使用Object類來建立自定義對象時,能夠無需定義構造函數(constructor,prototype,hasOwnProperty(property))閉包

1 var per = new Object(); 2 per.name = 'zhangsan'; 3 per.age = 30; 4 alert(per.name + per.age);

咱們想在程序中獲得一個對象變量,只要能存儲大量數據便可,這個時候,咱們能夠考慮使用Object類。Object類避免了對構造器的定義。 Object類下另外一個經常使用的屬性:hasOwnPropertyapp

1 var per = new Object(); 2 per.name = 'zhangsan'; 3 per.age = 30; 4 if per.hasOwnProperty('email'){ 5 alert('具備email'); 6 }else{ 7 alert('無email'); 8 }

 

2.靜態屬性函數

在有些面向對象的語言當中,可使用static關鍵字定義類的靜態屬性或者靜態方法,在JS中,能夠進行模擬。this

語法:spa

  類名.屬性名

  類名.屬性=function(){}

 1 function Person(){  2 }  3 Person.count = 0;  4 var p1 = new Person();  5 Person.count++;  6 var p2 = new Person();  7 Person.count++;  8 var p3 = new Person();  9 Person.count++; 10 alert(Person.count);

添加靜態屬性和靜態方法:

 1 function Person(){  2 Person.count++; //靜態屬性  3 Person.getCount=function(){ //靜態方法  4 alert('當前共有' + Person.count + '我的');  5  }  6 }  7 Person.count = 0;  8 var p1 = new Person();  9 var p2 = new Person(); 10 var p3 = new Person(); 11 Person.getCount();

 

3.閉包

概念:所謂閉包,指的是一個擁有許多變量和綁定了這些變量的環境的表達式(一般是一個函數),所以這些變量也是該表達式的一部分。

提出一個問題:

1 function display(){ 2 var i=10; 3 } 4 display(); 5 //在這裏,想訪問局部變量i

在全局中,不能訪問局部變量i,由於做用域不一樣,並且,在display函數執行完畢後,局部變量i會被回收。 閉包的功能:「訪問局部變量」和「使變量所佔的內存不被釋放」

1 //例1 2 function fn1(){ 3 function fn2(){ 4 alert('hello'); 5  } 6 return fn2; //返回fn2函數首地址 7 } 8 var test=fn1(); //test也指向了fn2函數的首地址 9 test();

經過例1咱們知道:變量是能夠指向函數的首地址的,函數也能夠返回另外一個函數的首地址。

 1 //例2  2 function fn1(){  3 var i = 10;  4 function fn2(){  5  alert(i);  6  }  7 return fn2; //返回fn2函數首地址  8 }  9 var test=fn1(); //test也指向了fn2函數的首地址 10 test();

經過例2咱們知道:使用一個拒不函數包含變量i,這樣局部變量i的內存不會被回收。

 1 //例3  2 function fn1(){  3 var i = 10;  4 function fn2(){  5 alert(i++);  6  }  7 return fn2; //返回fn2函數首地址  8 }  9 var test=fn1(); //test也指向了fn2函數的首地址 10 test(); 11 test(); 12 test();

在例3中,由於i的內存永遠不會被回收,因此每次調用fn2,i的值會+1。運行的結果是彈出10,彈出11,彈出12。

閉包的原理:在例3中,共有三個做用域:全局做用域,fn1的做用域,fn2的做用域。在全局做用域裏有test=fn1(),其實這句話就至關於test=fn2。在fn1做用域裏有 var i=10和return fn2,在fn2做用域例有alert(i++)。當全局做用域下的test=fn1()執行時,test指向了fn2的做用域,這個時候fn2做用域下的i被全局做用域鉤住,根據做用域鏈的法則,fn2下並無定義i,因此在fn2下的i往上一層做用域上找,找到了fn1做用域下的var i=10。因此全局的test鉤住了fn2的i,fn2的i鉤住了fn1的i,因此fn1運行完畢後,不會被回收。

 

4.私有屬性

在面向對象思想中,對於有些敏感的,不想公開的成員能夠定義爲私有的,在JavaScript中能夠模擬這個功能。

語法: 

function Person(p_name){

      var name = p_name;

  this.age

}

var :私有

this :公有

1 function Person(p_name,p_age){
2     this.name = p_name;
3     var age = p_age;
4 }
5 var p1 = new Person('zhangsan',30);
6 alert(p1.name);
7 alert(p1.age);

在上面這個例子中,咱們想用var來表示私有成員屬性,但Person構造函數執行完畢後,age會被回收,不能當作成員屬性來使用。

 1 function Person(p_name,p_age){
 2     this.name = p_name;
 3     var age = p_age;
 4     this.setAge=function(a){
 5         age = a;
 6     }
 7     this.getAge=function(){
 8         return(age);
 9     }
10 }
11 var p1 = new Person('zhangsan',30);
12 p1.setAge(20);
13 alert(p1.getAge());

this.setAge和this.getAge兩個方法使用到了局部變量age,因此age不會被回收。

若是隻有set方法,說明該屬性是隻寫屬性。

若是隻有get方法,說明該屬性是隻讀屬性。

 

5.call和apply的使用

call和apply的功能:使用指定的對象調用當前函數。call和apply的功能徹底相同,只是在語法上略有不一樣。

語法:

call([thisObj[,arg1[,arg2[,argN]]]])

第一個參數:函數執行時,this指向誰

後面的參數:根據須要順序指定

apply([thisObj[,argArray]])

第一個參數:函數執行時,this指向誰

第二個參數:數組,表示參數集合

在js中,函數有幾種調用形式:

Person();                      //Person內的this指向window

var p1=new Person();    //Person內的this指向p1

per.Person();                 //Person內的this指向per

 1 function Person(p_name,p_age){
 2     this.name = p_name;
 3     this.age = p_age;
 4 }
 5 function speak(){
 6     alert(this.name + this.age);
 7 }
 8 var p1 = new Person('zhangsan',30);
 9 //speak(); 這樣調用this指向window
10 //p1.speak(); p1對象沒有speak屬性

使用call和apply來調用

 1 function Person(p_name,p_age){
 2     this.name = p_name;
 3     this.age = p_age;
 4 }
 5 function speak(){
 6     alert(this.name + this.age);
 7 }
 8 var p1 = new Person('zhangsan',30);
 9 speak.call(p1);
10 speak.apply(p1);

call和apply在執行時作了兩件事:1)將函數內部this指向了第一個參數   2)調用函數

另外:還能夠這樣解決問題:

P1.say=speak;

P1.say();

這樣解決和上面解決方法有本質上的區別:

上面的解決辦法是直接調用speak函數,只不過函數內部this的指向發生改變。

下面的解決辦法會爲p1對象增長屬性,p1對象的「體積」會變大。

舉例說明:

 1 <script>
 2 function fn1(){
 3     this.style.color='red';
 4 }
 5 function fn2(){
 6     this.style.fontSize='50px';
 7 }
 8 window.onload=function(){
 9     document.getElementById('btn').onclick=function(){
10         var div1 = document.getElementById('div1');
11         fn1.call(div1);
12         fn2.apply(div1);
13     };
14 };
15 </script>
16 <div id='div1'>hello javascript</div>
17 <input type='button' id='btn' value='肯定'>

 

6.繼承的三種實現方法

概念:在有些面嚮對象語言中,可使用一個類(子類)繼承另外一個類(父類),子類能夠擁有父類的屬性和方法,這個功能能夠在js中進行模擬。

三種方法:

第一種:擴展Object方法

1 Object.prototype.方法=function(父類對象){
2     for(var i in 父類對象){
3         this[i] = 父類對象[i];
4     } 
5 };

舉例說明:

 1 Object.prototype.ext=function(parObject){
 2     //循環遍歷父類對象全部屬性
 3     for(var i in parObject){
 4         //爲子類對象添加這個遍歷到的屬性
 5         //它的值是父類對象這個屬性的屬性值
 6         this[i] = parObject[i];
 7     }
 8 }
 9 function Person(p_name,p_age){
10     this.name=p_name;
11     this.age=p_age;
12     this.speak=function(){
13         alert(this.name+this.age);
14     }
15 }
16 function Student(p_no){
17     this.no=p_no;
18     this.say=function(){
19         alert(this.no+this.name_this.age);
20     }
21 }
22 var stu = new Student(101);
23 stu.ext(new Person('xiaoqiang',20));
24 stu.speak();
25 stu.say();

第二種:使用call和apply方法

語法:

父類構造器.call(this,.......);

 1 function Person(p_name,p_age){
 2     this.name=p_name;
 3     this.age=p_age;
 4     this.speak=function(){
 5         alert(this.name+this.age);
 6     }
 7 }
 8 function Student(p_no,p_name,p_age){
 9     this.no=p_no;
10     this.say=function(){
11         alert(this.name+this.age+this.no);
12     }
13     Person.call(this,p_name,p_age);
14 }
15 var stu = new Student(8,'zhagsan',18);
16 stu.speak();
17 stu.say();

第三種:原型繼承

語法:

子類.prototype = new 父類();

 1 function Person(p_name,p_age){
 2     this.name=p_name;
 3     this.age=p_age;
 4     this.speak=function(){
 5         alert(this.name+this.age);
 6     }
 7 }
 8 function Student(p_no){
 9     this.no=p_no;
10     this.say=function(){
11         alert(this.name+this.age+this.no);
12     }
13 }
14 Student.prototype = new Person('wangwu',21);
15 var stu = new Student(10);
16 stu.speak();
17 stu.say();
相關文章
相關標籤/搜索