对象的属性:
私有属性(var)、类属性(静态属性)、对象属性(this)、原型属性(prototype)。
对象的方法:
私有方法(funtion)、类方法(静态方法)、对象方法(this)、原型方法(prototype)。
类方法/静态方法:
类名.方法名 = function(参数1,参数2...参数n)
{
//方法代码
}
对象方法:this指针(公有方法/特权方法)
原型方法:
类名.prototype.方法名 = function(参数1,参数2...参数n)
{
//方法代码
}
1.私有属性 私有方法:只能在这个函数里使用这个属性或方法
function User(name,age){
var name = name;//私有属性
var age = age;
function alertAge(){//私有方法
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>