《js高级程序设计》之面向对象编程

1,js中没有类的概念,js中的对象类似于散列表(键:值)

2,创建对象可以:

var obj=new Object();

obj.name="bob";

obj.sayname=function(){
alert(this.name);}

也可以使用对象字面量创建对象:

var obj={

name: "bob",

sayname:function(){ };

}

3, 对象中的属性:

***数据属性有四个特征:

configurable:能否通过delete删除属性并重新定义

Enumerable:表示能否通过for-in循环返回属性;

writeble:能否修改属性值;

value:属性的值;

使用object.defineProperty()修改以上四个特征;这个方法有三个参数:对象名,属性名,以及要修改的内容;

var person = {};

Object.defineProperty(person, "name",

{     writable: false,  

  value: "Nicholas"  

}); 

***访问器属性:

configurable:能否通过delete删除属性并重新定义;

Enumerable:能否通过for-in循环;

get:在读取属性是定义的函数;

set: 在设置属性时定义的函数;

Object.defineProperty(对象名,属性名,{

set:function(){ };

get: function(){ };

})

***定义多个属性:

object.definedeProperties(对象名,{

name:{

value:"bob"  

},

age:{

value: 12

},

year:{

 set: function(){},

get:function(){ }}}

***利用obj.getOwnPropertyDescriptor()

可以返回对象的属性

var obj1=obj.getOwnPropertyDescriptor(对象名,属性名);

alert(obj1.value);

4,工厂模式:

如果想实例化多个对象,若使用面向字面量或者构造函数形式会造成大量重复代码:所以使用工厂模式;

function  createPerson(name, age, job){

var  o=new  Object();

o.name=name;

o.age=age;

o.job=job;

rerturn o;

}

var object1=createPerson("bob", 12, "engineer");

var object2=createPerson("Amy", 22, "doctor");

5,除了工厂模式还有构造函数模式:

  function  Person(name,age,job){

this.name=name;.

this.age=age;

this.job=job;

}

var  object1=new Person("bob" ,12, "student");

注意:构造函数模式没有在函数内部创建对象,而是在创建实例化对象的时候new的;

当object1创建一个对象的时候,这个构造函数的作用域赋给了它,所以this指向它;

但是构造函数的方法在内部实现时:

function  Person(){
this.sayName=new Function(){ };

}    //相当于

function Person(){
this.sayName=sayName;

}

function  sayName(){  };

6,任何函数只要被调用的时候前面加上new,都是构造函数,并且函数中的this指向这个对象;若只是被普通调用,那么它就是个普通函数,并且this指向window;

还有一种操作:

var  o=new object();

Person.call(o, "Amy", 23, "teacher");

o.name  ;  //Amy;

这段代码的意思是:将构造函数Person的所有属性方法全部复制给对象O;

可以使用 call()(或者 apply())在某个特殊对象的作用域中 调用Person()函数。这里是在对象o的作用域中调用的,因此调用后o就有了所有属性和sayName() 方法。 

7, 原型模式(prototype):

每个函数都有prototype属性,用来额外给自己增加属性,马上你就会知道:

function  main(){  };

main.prototype.name="Bob";

原型模式和构造函数不同之处:构造函数中每个对象自身创建的实例并不会分享给别的对象实例;

但是原型模式由于是把属性加到原型对象中,所i以所有的对象都可以共享属性;

原型对象:函数A被创建的时候,浏览器会自动生成一个对象B,函数A默认拥有属性prototype,这个属性指向对象B(也就是A.prototype代表B),而对象B也有一个属性constructor,指向函数A(也就是A.prototype.constructor代表A);如果A创建了一个实例,那么它是构造函数,它的实例化对象内部会自动生成一个属性[[prototype]],这个属性指向了函数的原型对象(实际上实例化对象和构造函数是没有关系的)。所以要想判断一个实例化对象a1的原型对象是谁,可以使用方法isPrototypeOf(),A.Prototype.isPrototype(a1); //true 还有一种方法:Object.getPrototype(a1) ;//A.Prototype;我们在调用实例化对象的属性时,首先会在实例化对象中寻找,找不到就在原型对象中寻找,所以实例化对象不可以修改原型对象中  的属性,只能调用,所以如果在实例化对象中创建一个和原型对象同名的属性,即使将这个属性设置为null,也无法再调用原型对象中的同名属性,除非使用delete直接将实例化中的同名属性删除;利用hasOwnProperty()方法可以检查某个属性到底属于实例化对象还是原型对象:a1.hasOwnProperty(属性名),如果有 就返回true;而in操作符可以判断实例化对象中有没有某个属性(无论这个属性是存在实例化对象中还是原型对象中,只要有,就返回true;)    alert( "name"  in  a1);//true; 利用hasOwnProperty()和in操作符可以准确判断某个属性到底存在哪里;

利用prototype增加属性,可以利用重写原型对象:

function Person(){  };

Person.prototype={

name:"bob",

age:12}

虽然方便但是此时的constructor不再指向构造函数Person,而是指向Object构造函数;

可以在构造函数中直接添加来解决:

function Person(){  };

Person.prototype={

constructor:  Person          }

还有一个问题,就是如果此时再实例化一个对象,这个对象由于一直指向的是构造函数的原型对象,而不指向重写的原型对象,所以无法调用这些重写的属性方法;


 

猜你喜欢

转载自blog.csdn.net/kalinux/article/details/82559718