继承
1.原型对象链和 Object.prototype
hasOwnProperty() //检查是否存在一个给定名字的自有属性
propertyIsEnumerable() //检查一个自有属性是否可枚举
isPrototypeOf() //检查一个对象是否是另一个对象的原型对象
valueOf() //返回一个对象的表达式
toString() //返回一个对象的字符串表达
<script>
Object.prototype.add = function(value){
return this + value;
};
var book = {
title:"hello world"
};
console.log(book.add(5));
console.log("title".add("end"));
</script>
2.对象继承(Object.create)
<script>
var person1 = {
name:"Anqi",
sayName:function(){
console.log(this.name);
}
};
var person2 = Object.create(person1,{
name:{
configurable:true,
enumerable:true,
value:"Hello",
writable:true
}
});
person1.sayName();
person2.sayName();
</script>
3.构造函数的继承(两种方式)
<script>
function Rectangle(length,width){
this.length = length;
this.width = width;
}
Rectangle.prototype.getArea = function(){
return this.length * this.width;
};
Rectangle.prototype.toString = function(){
return "[Rectangle" + this.length + "x" + this.width + "]";
};
function Square(size){
this.length = size;
this.width = size;
}
// Square.prototype = new Rectangle();
// Square.prototype.constructor = Square;
// 上面这段注释改写成下面这段
Square.prototype = Object.create(Rectangle.prototype,{
constructor:{
configurable:true,
enumerable:true,
value:Square,
writable:true
}
});
Square.prototype.toString = function(){
return "[Square" + this.length + "x" + this.width + "]";
};
var rect = new Rectangle(5,10);
var square = new Square(6);
console.log(rect.getArea());
console.log(square.getArea());
console.log(rect.toString());
console.log(square.toString());
</script>
【重要的两段代码】
Square.prototype = new Rectangle();
Square.prototype.constructor = Square;
Square.prototype = Object.create(Rectangle.prototype,{
constructor:{
configurable:true,
enumerable:true,
value:Square,
writable:true
}
});
3.构造函数的窃取
用 call() 和 apply() 是构造函数窃取的关键。
<script>
function Rectangle(length,width){
this.length = length;
this.width = width;
}
Rectangle.prototype.getArea = function(){
return this.length * this.width;
};
Rectangle.prototype.toString = function(){
return "[Rectangle" + this.length + "x" + this.width + "]";
};
function Square(size){
Rectangle.call(this,size,size);
}
Square.prototype = Object.create(Rectangle.prototype,{
constructor:{
configurable:true,
enumerable:true,
value:Square,
writable:true
}
});
Square.prototype.toString = function(){
return "[Square" + this.length + "x" + this.width + "]";
};
var square = new Square(6);
console.log(square.length);
console.log(square.width);
console.log(square.getArea());
</script>
4.访问父类方法
Square.prototype.toString = function(){
var text = Rectangle.prototype.toString.call(this);
return text.replace("Rectangle","Square");
};
该方法只需把 Square.prototype.toString 改成 Rectangle.prototype.toString ,这是唯一访问父类的方法。
对象模式
1.模块模式
模块模式是一种用于创建拥有私有数据的单件对象的模式。
<script>
var person =(function(){
var age=25;
return{
name:"Anqi",
getAge:function(){
return age;
},
setAge:function(value){
age=value
}
}
})();
person.setAge(20);
console.log(person.getAge())
</script>
以下是更改后的暴露模块模式
<script>
var person = (function(){
/*私有*/
var age=25;
function getAge(){
return age;
}
function setAge(value){
age=value;
}
return{
/*共有的*/
name :"Anqi",
getAge:getAge,
setAge:setAge
}
})();
</script>
2.构造函数的私有成员
在构造函数中定义私有数据
<script>
/*在构造函数中定义私有数据*/
function Person(name){
//私有
var age;
this.getAge = function(){
return age;
};
this.setAge = function(value){
age = value;
};
this.name=name;
}
var anqi = new Person("Anqi");
anqi.setAge(24);
console.log(anqi.getAge())
</script>
3.作用域安全的构造函数
当你不用 new 操作符直接调用来改变this的值,会遇到错误
<script>
function Person(name){
this.name = name;
}
Person.prototype.sayName=function(){
console.log(this.name)
};
var Anqi = Person("anqi");
console.log(Anqi instanceof Person); // false
console.log(typeof Anqi); // undefined
</script>
可以使用这种模式来根据 new 的使用与否来控制函数的行为。
function Person(name){
if(this instanceof Person){
this.name = name;
}else{
return new Person(name);
}
}