Javascript面向对象
1.理解对象
(1) 属性类型
①数据属性
1)configurable 可定义、delete、修改 默认true
2)enumerable 可for-in返回属性 默认true
3)writable 可修改值 默认true
4)value 读取该属性的时候,从这个位置读;写入该属性的时候,把新值保存在这个位置。
对象:
var person = {
name: "Nicholas"
}
Object.defineProperty(person, "name", {
value: "cao",
configurable: /*false*/true
});
函数对象:
function Person(name) {
this.name = name;
Object.defineProperty(this, "name", {
value: "cao"
});
}
configurable 设置为false非严格模式下delete不删除不报错,严格模式下报错。
一旦把属性定义为不可配置的,就不能再改回可配置的。再配置writable等会报错。
用Object.defineProperty()定义新属性,如果不指定,默认configurable enumerable writable默认为false。
不要在IE8中用Object.defineProperty()
②访问器属性
1)configurable 可定义、delete、修改 默认true
2)enumerable 可for-in返回属性 默认true
3)get
4)set
没有定义set则不能写,严格模式下赋值会报错。
var book = {
_year: 2004,
edition: 1
}
Object.defineProperty(book, "year", {
get: function() {
return this._year;
},
set: function(value) {
if (value > 2004) {
this._year = value;
this.edition += value - 2004;
}
}
});
console.log(book.year);
定义访问器的旧方法:
book.__defineGetter__("year", function() {
return this._year;
});
book.__defineSetter__("year", function(value) {
if (value > 2004) {
this._year = value;
this.edition += value - 2004;
}
});
(2)定义多个属性 IE9+ 和其它…
Object.defineProperties(book, {
_year: {
writable: true,
value: 2004
},
edition: {
writable: true,
value: 1
},
year: {
get: function() {
return this._year;
},
set: function(value) {
this._year = value;
}
}
});
(3)读取属性的特性
var descriptor1 = Object.getOwnPropertyDescriptor(book, "year");
console.log(descriptor1.configurable);
console.log(typeof descriptor1.get);
console.log(typeof descriptor1.set);
2.创建对象
(1)工厂模式
(2)构造函数模式
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
console.log(this.name);
}
}
var o = new Object();
Person.call( o, "许魏洲", 24, "singer" );
o.sayName();
(3)原型模式
//Person.prototype.constructor 指向 Person
//proto属性默认存在 是实例与构造函数原型之间的连接 实例没有prototype属性
// isPrototypeOf() 判断实例原型指针是否指向指向调用者
//实例赋给属性新值 原型的同名属性被覆盖,将实例的属性delete后才能再次访问到原型的属性值
//hasOwnProperty()方法 实例属性返回true 原型属性返回false getOwnPropertyDesciptor() 原型属性
//判断原型属性
function hasOwnPrototypeProperty(object, name) {
return !object.hasOwnProperty(name) && (name in object);
}
这种方法创建的原型 constructor不指向源构造函数 指向Object构造函数,可以显示设置回去解决问题,但以这种方式设置的构造函数可枚举,原生的是不可枚举的,可通过Object.defineProperty()设置不可枚举。
function Animal() {
if (typeOf this.sayName) { //动态添加原型
Animal.prototype.sayName = function() {
console.log("name: " + this.name);
}
}
}
Animal.prototype = {
constructor: Animal,
name: "旺财",
age: 0.6,
sayName: function(){
console.log(this.name);
}
}
Object.defineProperty(Animal.prototype, "constructor", {
enumerable: false,
value: Animal
});
//重写原型对象切断了原型与之前已经存在的实例之间的联系,
//实例引用的仍然是之前的原型,解决办法是动态添加原型
(4)组合使用构造函数模式和原型模式 最常用
(5)动态原型模式
(6)寄生构造函数模式 和工厂模式没有什么不同
(7)稳妥构造函数模式
和构造函数无关,不用this,实例化不用new。
3.继承
(1)原型链
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,
而实例都包含一个指向原型对象的内部指针。
给原型添加方法的代码一定要放在替换原型的代码之后。
不能字面量方式重写原型,这样就会切断原有的链式联系。
原型链的两个问题:
1)原型中的引用类型
底层实例 和父实例 都继承了父亲的原型,都可操作父原型里面的对象
2)不能向父类型的构造函数中传参
(2)借用构造函数 没有用到链式
function SuperType(name) {
this.name = name;
}
SuperType.prototype.sex = "男";
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
SubType.prototype.appr = "帅";
var mm = new SubType("mm", 21);
console.log(mm.name + " " + mm.age + " " + mm.sex+ " " + mm.appr);
// mm 21 undefined 帅
问题:1) 在超类型原型定义的方法,子类型的实例是不可见的。
2) 方法都得定义在构造函数中,函数复用无从谈起
(3)组合继承 (集前两者优点,同时解决了问题,最为常用)
function SuperType(name) {
this.name = name;
}
SuperType.prototype.sex = "男";
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
SubType.prototype = new SuperType();
//SubType.prototype.constructor = SubType;
SubType.prototype.appr = "帅";
var mm = new SubType("mm", 21);
console.log(mm.name + " " + mm.age + " " + mm.sex + " " + mm.appr);
(4)原型式继承 不想用构造函数实现继承
function object(o) {
function F(){}
F.prototype = o; //浅复制
return new F();
}
ECMAScript5实现了这一方法
Object.create()
参数1:Object.create(o)
参数2:Object.create(o, {
name: {
value: “mm”
}
})
(5)寄生式继承 由于不能做到函数复用降低了效率 如sayName
var House = {
name: "万达",
address: "西安"
}
function createAnother(o) {
var clone = object(o);
clone.sayName = function() {
console.log("寄生继承: " + this.address
);
};
return clone;
}
var b = createAnother(House);
b.sayName();
(6)寄生组合式继承
function inheritPrototype(subType, superType) {
var prototype = object(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
本质上是使用寄生式继承来继承超类型的原型
避免了在SubType.prototype上创建不必要的属性。解决了SubType.prototype = new SuperType()导致的在SubType.prototype上创建不必要的属性的问题。
4.动态添加节点
(1)createElement setAttribute 等设置属性
(2)innerHTML添加
(3)jquery版本
5. 前端对象
(1)BOM
①Window
②Document
③History
④Screen
⑤Navigtor
(2)内置对象
①Cookie
②Session
③Math
④String
⑤Date
⑥Array
⑦RegExp
⑧Number
⑨Object
⑩Function
⑪Null
⑫Boolean
⑬Error
(3)自定义对象
6. 函数对象返回对象 需new实例化得到对象
函数返回字符串 相当于返回this 不返回默认返回this
函数内部给未声明的变量赋值,需要函数执行后,该变量才会变成window全局变量