對象的屬性:
私有屬性(var)、類屬性(靜態屬性)、對象屬性(this)、原型屬性(prototype)。javascript
對象的方法:java
私有方法(funtion)、類方法(靜態方法)、對象方法(this)、原型方法(prototype)。node
類方法/靜態方法:
類名.方法名 = function(參數1,參數2...參數n)
{
//方法代碼
}
對象方法:this指針(公有方法/特權方法)
原型方法:安全
類名.prototype.方法名 = function(參數1,參數2...參數n)
{
//方法代碼
}閉包
1.私有屬性 私有方法:只能在這個函數裏使用這個屬性或方法函數
function User(name,age){性能
var name = name;//私有屬性學習
var age = age;測試
function alertAge(){//私有方法this
alert(age);
}
alertAge(age); //彈出26
}
var user = new User('fire子海',26);
私有屬性也能夠經過閉包獲取。
2.靜態屬性: 公共屬性,直接屬於某個類,即類屬性(js沒有類,這裏只是指構造函數)
靜態屬性的定義方式是:
類名.屬性名=屬性值; 使用 【類名.屬性名】 調用
靜態方法:只有類才能訪問類屬性和方法,實例不能訪問,只能經過對象自己調用靜態方法和靜態屬性。
靜態屬性方法是暴露給外部的,掛在類上面的,不屬於任何實例。
靜態方法沒法調用公有屬性、公有方法、私有方法、私有屬性、特權方法、原型屬性
靜態方法的定義方式是:
類名.方法名 = function(參數1,參數2...參數n)
{
//方法代碼
}
若是兩個函數都調用這個靜態方法,刪除其中一個函數中的靜態方法,則對應的另外一個函數的靜態方法也被刪除。
靜態方法表現形式:
Eg1:
function User(){}
User.age = 26;//靜態屬性
User.myname = 'fire子海';
User.getName =function(){//靜態方法
return this.myname;
}
console.log(User.getName());//output:fire子海
Eg2://靜態類 字面量方式
var user = {
init:function(name,age){ //靜態方法
this.name = name;
this.age = age;
},
getName:function(){
return this.name;
}
}
user.init('fire子海',26);
console.log(user.getName());//output:fire子海
Eg3://靜態方法不能實例訪問
function User(){}
User.age = 26;//靜態屬性
User.myname = 'fire子海';
User.getName =function(){//靜態方法
return this.myname;
}
var user = new User();
console.log(user.getName);//undefined 或者user.getName()返回TypeError: user.getName is not a function
user.supper = '方便麪';
user.eat = function(){
return '晚餐只有'+this.supper;
}
user.eat();//晚餐只有方便麪 //給new對象加方法因此能夠調用
Eg4://構造函數+原型
function User(){
this.myname = 'fire子海';//公有屬性
this.age = 26;
this.do = function(){//特權方法
return this.myname+'學習js';
}
}
User.prototype.alertAge = function(){//公共方法,也叫原型方法
alert(this.age);
}
User.prototype.sex = '男';//原型屬性
User.getName= function(){//靜態方法
return this.myname;
}
User.getAge = function(){
this.alertAge();
}
User.getDo = function(){
return this.do();
}
//console.log(User.getName())//undefined 靜態方法不能調用公有屬性
//console.log(User.getDo());//TypeError: this.do is not a function //靜態方法不能調用特權方法
//console.log(User.getAge())//TypeError: this.alertAge is not a function//靜態方法不能調用原型方法和原型屬性
3.公有屬性:(即實例屬性、特權屬性,)在對象實例化後調用。
公有方法的調用規則:
公有方法能被外部訪問並調用的方法。經過對象自己調用,即對象名。公有方法不能調用私有屬性和方法。
公有方法和特權方法並無什麼本質上的區別,緣由在於這個概念是來自於使用構造函數建立私有數據的時候定義出來的。
Eg:
var BaseClass = function() {
this.method1 = function(){
alert(' Defined by the "this" in the instance method');
}
};
var instance1 = new BaseClass();
instance1.method1 = function(){
alert(' Defined directly in the instance method');
}
BaseClass.prototype.method1 = function(){
alert(' Defined by the prototype instance method ');
}
instance1.method1();//Defined directly in the instance method
經過運行結果跟蹤測試能夠看出直接定義在實例上的變量的優先級要高於定義在「this」上的,而定義在「this」上的又高於 prototype定義的變量。即直接定義在實例上的變量會覆蓋定義在「this」上和prototype定義的變量,定義在「this」上的會覆蓋prototype定義的變量。
直接定義變量>this定義變量>prototype定義變量
Eg://構造函數+原型
function User(){
this.myname = 'fire子海';//公有屬性
this.age = 26;
this.do = function(){ //特權方法
return this.myname+'學習js';
}
}
User.eat = function(food){ //靜態方法
return '晚餐只有'+food;
}
User.prototype.alertAge = function(){//原型方法 能夠調用公有屬性/實例屬性
alert(this.age);
}
User.prototype.alertDo = function(){
alert(this.do());//原型方法能夠調用特權方法
}
User.prototype.alertEat = function(food){
alert(User.eat(food));//只能經過對象自己調用靜態方法
//alert(this.ear(food))這樣調用將出錯:this.eat is not a function
}
var user = new User();
user.alertAge();//alert:26
user.alertDo();//alert:fire子海學習js
user.alertEat('方便麪')//alert:晚餐只有方便麪
4.原型屬性 原型方法
原型屬性:類名.prototype.屬性名 = 屬性值;
原型方法:
類名.prototype.方法名 = function(參數1,參數2...參數n)
{
//方法代碼
};
User.prototype.alertAge = function(){//公共方法,也叫原型方法
alert(this.age);
}
User.prototype.sex = '男';//原型屬性
看成是類內部的屬性使用【this.原型屬性】,也能夠當成公有靜態屬性使用【對象.prototype.原型屬性】 靜態方法不能調用原型屬性
原型方法能夠實例化對象調用,也可靜態方法調用
在實例上不能使用prototype,不然發生編譯錯誤
Eg:
var obj = new Object();
obj.prototype.Property = 1; //Error
obj.prototype.Method = function(){alert(1); }//Error
每一個由構造器建立的對象擁有一個指向構造器 prototype 屬性值的 隱式引用(implicit reference),這個引用稱之爲 原型(prototype)。進一步,每一個原型能夠擁有指向本身原型的 隱式引用(即該原型的原型),如此下去,這就是所謂的 原型鏈(prototype chain)。在具體的語言實現中,每一個對象都有一個 __proto__ 屬性來實現對原型的 隱式引用。
有了 原型鏈,即可以定義一種所謂的 屬性隱藏機制,並經過這種機制實現繼承。
<script type="text/javascript"> //子類如何重寫父類的屬性或方法
function AClass() {
this.Property = 1;
this.Method = function() { alert(1); }
}
function AClass2(){
this.Property2 = 2;
this.Method2 = function() {alert(2); }
}
AClass2.prototype = new AClass();
AClass2.prototype.Property = 3;
AClass2.prototype.Method = function() { alert(4); }
var obj = new AClass2();
alert(obj.Property); //3
obj.Method(); //4
</script>
靜態方法和實例方法區別:
固然你徹底能夠把全部的實例方法都寫成靜態的,將實例做爲參數傳入便可,通常狀況下可能不會出什麼問題。
從面向對象的角度上來講,在抉擇使用實例化方法或靜態方法時,應該根據是否該方法和實例化對象具備邏輯上的相關性,若是是就應該使用實例化對象,反之使用靜態方法。
若是從線程安全、性能、兼容性上來看,也是選用實例化方法爲宜。
<script type="text/javascript">
var fun = {
//下面是靜態方法(第一種方式)
f1: function () {
alert("這是靜態方法 f1()");
},
f2:function(callback){
alert("這是靜態方法 f2()");
if(callback && (callback instanceof Function)){
callback();//回調方法
}
}
}
var c = function () {
//實例方法
this.f1=function(){
alert("這是實例方法 c.f1()");
}
}
//下面是靜態方法(第二種方式)
c.f2 = function () {
alert("這是靜態方法 c.f2()");
}
callbackfun = function () {
alert("這是定義好的回調方法!");
}
$(function () {
var node = document.getElementById('test');
node.onclick = function () {
//調用靜態方法
fun.f1();
//調用回調方法
fun.f2(function () { alert("這是回調方法!");});
fun.f2(callbackfun);
//調用靜態方法
c.f2();
//調用實例方法
var c1 = new c();
c1.f1();
//c1.f2();//這樣不能調用會報錯
//alert(typeof (fun));//obj
//alert(typeof (fun.f1));//function
//alert(typeof(c.f2)); //function
//var c1 = new c();
//alert(typeof (c));//function
//alert(typeof(c1));//object
//alert(typeof(c1.f1));//function
}
});
</script>