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