//工厂模式
//解决了重复实例化,但是有识别问题
function createObject(name, age){
var obj = new Object(); //创建对象
obj.name = name; //添加属性
obj.age = age;
obj.run = function(){ //添加方法
return this.name + this.age + '运行中...';
};
return obj; //返回对象引用
}
var box = createObject('Lee', 100); //创建对象
var box1 = createObject('Jack', 200);
alert(box.run()); //打印对象方法
alert(box1.run());
//*************************************************构造函数
//解决了重复实例化,解决识别问题,改良后的工厂方法
function Box(name, age){ //创建对象
this.name = name; //添加属性
this.age = age;
this.run = function(){
return this.name + this.age + '运行中...';
};
}
function Desk(name, age){ //创建对象
this.name = name; //添加属性
this.age = age;
this.run = function(){
return this.name + this.age + '运行中...';
};
}
//1.构造函数没有new Object,但是后台会自动var obj = new Object();
//2.this就相当于obj
//3.构造函数不需要返回对象引用,后台自动返回
//规范1.构造函数也是函数,但函数名第一个字母要大写
//2.必须new 构造函数名(),new Box(),而且这个Box第一个字母也是大写的
//3.必须使用new运算符
var box = new Box('Lee', 100); //实例化
var box1 = new Box('Jack', 200);
var box2 = new Desk('kkk', 300);
// alert(box.run()); //打印对象方法
// alert(box1.run());
console.log(box instanceof Box);
console.log(box1 instanceof Box);
console.log(box2 instanceof Box); //可以识别
console.log(box2 instanceof Desk);
//*************************************************对象冒充
function Box(name, age){ //创建对象
this.name = name; //添加属性
this.age = age;
this.run = function(){
return this.name + this.age + '运行中...';
};
}
var o = new Object();
Box.call(o, 'Lee', '100'); //对象冒充
alert(o.run());
//**************************************************引用地址一致性,不好
//外部函数解决,不好
function Box(name, age){ //创建对象
this.name = name; //添加属性
this.age = age;
this.run = run;
}
function run(){ //把构造函数内部方法通过全局来保证引用地址一致性
return this.name + this.age + '运行中...';
}
var box = new Box('Lee', 100);
var box1 = new Box('Lee', 100);
// alert(box.name == box1.name);
// alert(box.age == box1.age);
// alert(box.run() == box1.run());
// alert(box.run); //方法的引用地址
alert(box.run == box1.run); //因为比较他们实例化地址
alert(run());
//**************************************************原型模式方式,引用地址一致,好
function Box(){} //构造函数函数体内什么都没有,这里如果有,叫做实例属性,实例方法
Box.prototype.name = 'Lee'; //原型属性 __proto__
Box.prototype.age = 100;
Box.prototype.run = function(){ //属性方法
return this.name + this.age + '运行中...';
}
var box = new Box();
box.name = 'Jack'; //实例属性,并没有重写原型属性
console.log(box.name); //就近原则,先查找实例属性和方法,没有在去找原型属性和方法
// console.log(box.hasOwnProperty('name')); //判断是否是实例属性
delete box.name;
console.log(box.name);
// delete Box.prototype.name;
// Box.prototype.name = 'kkk';
alert('name' in box); //实例或原型都有就返回true
var box1 = new Box();
// console.log(box1.name); //实例属性不会共享,所以box1访问不到box的实例属性
alert(isProperty(box1, 'name'));
// console.log(box.age);
// console.log(box.run());
// console.log(box.run == box1.run); //true
// console.log(box.prototype); //实例访问不到prototype,这个属性是对象,访问不到
// console.log(box.__proto__); //这个属性是指针,指向prototype圆形对象,ie不支持打印
//console.log(Box.prototype); //使用对象名访问prototype
// console.log(box.constructor); //构造属性,可以获取构造函数本身Box()
// //作用是被原型指针定位,然后得到构造函数本事
// //其实就是 对象实例 对应的 原型对象 的作用
// console.log(box1.name);
//判断依个对象实例(对象引用)是否指向原型对象,基本上,只要实例化了,自动指向
// console.log(Box.prototype.isPrototypeOf(box));
// var obj = new Object();
// console.log(Box.prototype.isPrototypeOf(obj));
function isProperty(object, proterty){
return !object.hasOwnProperty(proterty) && (proterty in object);
}
//***************************************************
//字面量的方式创建原型对象,这里的{}就是对象,而且是Object, new Object() = {}
function Box(){};
Box.prototype = {
constructor : Box, //强制指向Box
name : 'Lee',
age : 100,
run : function(){
return this.name + this.age + '运行中...';
}
};
// var box = new Box();
// console.log(box.constructor); //Object
Box.prototype = {
age : 200 //这里不会保留之前原型的任何信息,
} //把原来的原型对象和构造函数对象实例之前的关系切断了
var box = new Box();
console.log(box.name);
// var box = [2,34,5,2,3,6,7,4,75];
// console.log(box.sort());
//查看sort是否是Array原型对象里的方法
// alert(Array.prototype.sort);
// alert(String.prototype.substring);
//内置引用类型的功能扩展
String.prototype.addstring = function(){
return this + '被添加的...';
}
var box = 'Lee';
alert(box.addstring());
function Box(){};
Box.prototype = {
constructor : Box, //强制指向Box
name : 'Lee',
age : 100,
family : ['哥哥', '姐姐', '妹妹'],
run : function(){
return this.name + this.age + '运行中...';
}
};
var box = new Box();
alert(box.family);
box.family.push('弟弟'); //在第一个实例修改后引用类型,保持了共享
alert(box.family);
var box1 = new Box();
alert(box1.family); //共享了box添加后引用类型的原型
//组合构造函数 + 原型模式
function Box(name, age){ //保持独立的用构造函数
this.name = name;
this.age = age;
this.family = ['哥哥', '姐姐', '妹妹'];
}
Box.prototype = { //保持共享的用原型
constructor : Box,
run : function(){
return this.name + this.age + '运行中...';
}
}
var box = new Box('Lee', 100);
console.log(box.run());
alert(box.family);
box.family.push('弟弟'); //在第一个实例修改后引用类型,保持了共享
alert(box.family);
var box1 = new Box('Jack', 200);
console.log(box1.run());
alert(box1.family); //引用类型没有使用原型,所以没有共享
//动态原型模式
function Box(name, age){ //保持独立的用构造函数
this.name = name;
this.age = age;
this.family = ['哥哥', '姐姐', '妹妹'];
if(typeof this.run != 'function'){ //判断this.run是否存在,初始化一次
Box.prototype.run = function(){
return this.name + this.age + '运行中...';
}
}
}
//原型初始化,只要第一次初始化就可以了,没必要每次构造函数实例化的时候都初始化
var box = new Box('Lee', 100);
console.log(box.run());
var box1 = new Box('Jack', 200);
console.log(box1.run());
//寄生构造函数 = 工厂模式 + 构造函数
function Box(name, age){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.run = function(){
return this.name + this.age + '运行中...';
}
return obj;
}
var box = new Box('Lee', 100);
console.log(box.run());
var box1 = new Box('Jack', 200);
console.log(box1.run());
//稳妥构造函数
function Box(name, age){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.run = function(){
return this.name + this.age + '运行中...';
}
return obj;
}
var box = Box('Lee', 100);
console.log(box.run());
//继承,通过原型链实现
function Box(){ //被继承的函数叫超类型(父类,基类)
this.name = 'Lee';
}
function Desk(){ //继承的函数叫做子类型(子类,派生类)
this.age = 100;
}
function Table(){
this.level = 'AAAAA';
}
//超类型实例化后的对象实例,赋值给子类型的原型属性
//new Box()会将Box构造里的信息和原型里的信息都交给Desk
//Desk的原型,得到的是Box的构造+原型里的信息
Desk.prototype = new Box();
Table.prototype = new Desk();
var box = new Box();
alert(box.constructor);
var desk = new Desk();
console.log(desk.age);
console.log(desk.name);
var table = new Table();
console.log(table.name);
console.log(table.level);
function Box(){ //被继承的函数叫超类型(父类,基类)
this.name = 'Lee';
}
Box.prototype.name = 'Jack';
function Desk(){ //继承的函数叫做子类型(子类,派生类)
this.age = 100;
}
Desk.prototype = new Box();
var box = new Box();
var desk = new Desk();
console.log(desk.name); //就近原则,实例有就返回,没有就找原型
//子类型从属于自己或者他的超类型
console.log(desk instanceof Object);
console.log(desk instanceof Desk);
console.log(desk instanceof Box);
console.log(box instanceof Desk);
//对象冒充继承
function Box(name, age){
this.name = name;
this.age = age;
// this.family = ['哥哥', '姐姐', '妹妹']; //引用类型放在构造里就不会共享
}
Box.prototype.family = ['哥哥', '姐姐', '妹妹'];
function Desk(name, age){
Box.call(this, name, age); //对象冒充,只能继承构造里的信息
}
var desk = new Desk('Lee', 100);
console.log(desk.name);
console.log(desk.family);
function Box(name, age){
this.name = name;
this.age = age;
this.family = ['哥哥', '姐姐', '妹妹']; //引用类型放在构造里就不会共享
}
Box.prototype.run = function(){
return this.name + this.age + '运行中...';
}
function Desk(name, age){
Box.call(this, name, age); //对象冒充,只能继承构造里的信息
}
var desk = new Desk('Lee', 100);
console.log(desk.name);
console.log(desk.family);
console.log(desk.run()); //继承不到prototype
var desk1 = new Desk('Lee', 100);
//组合继承 原型链 + 借用构造函数
//解决1构造传参,2原型链方法继承,3方法共享
function Box(name, age){
this.name = name;
this.age = age;
this.family = ['哥哥', '姐姐', '妹妹']; //引用类型放在构造里就不会共享
}
Box.prototype.run = function(){
return this.name + this.age + '运行中...';
}
function Desk(name, age){
Box.call(this, name, age); //对象冒充,只能继承构造里的信息
}
Desk.prototype = new Box();
var desk = new Desk('Lee', 100);
console.log(desk.name);
console.log(desk.family);
console.log(desk.run()); //继承不到prototype
var desk1 = new Desk('Lee', 100);
//原型式继承,问题:引用类型共享了
//临时中转函数
function obj(o){ //o表示将要传递进入的一个对象
function F(){}; //F构造是一个临时新建的对象,用来存储传递过来的对象
F.prototype = o; //将o对象实例赋值给F构造的原型对象
return new F(); //最后返回这个得到传递过来对象的对象实例
}
//F.prototype = 0 就相当于 Desk.prototype = new Box()
//这是字面量声明方式,相当于var box = new Box();
var box = {
name : 'Lee',
age : 100,
family : ['哥哥', '姐姐', '妹妹']
};
//box1就等于new F();
var box = obj(box);
console.log(box.name);
console.log(box.family);
box.family.push('弟弟');
console.log(box.family);
var box1 = obj(box);
console.log(box.family); //引用类型的属性共享了
//寄生式继承 = 原型式 + 工厂模式
//临时中转函数
function obj(o){
function F(){}
F.prototype = o;
return new F();
}
//寄生函数
function create(o){
var f = obj(o);
f.run = function(){
return this.name + '方法...';
}
return f;
}
var box = {
name : 'Lee',
age : 100,
family : ['哥哥', '姐姐', '妹妹']
};
var box = create(box);
console.log(box.run());
//寄生组合继承
//临时中转函数
function obj(o){
function F(){}
F.prototype = o;
return new F();
}
//寄生函数
function create(box, desk){
var f = obj(box.prototype);
f.constructor = desk; //调整原型构造指针
desk.prototype = f;
}
function Box(name, age){
this.name = name;
this.age = age;
if(typeof this.run != 'function'){ //判断this.run是否存在,初始化一次
Box.prototype.run = function(){
return this.name + this.age + '运行中...';
}
}
}
function Desk(name, age){
Box.call(this, name, age); //对象冒充
}
//通过寄生组合继承来实现继承
create(Box, Desk); //替代Desk.prototype = new Box();
var desk = new Desk('Lee', 100);
alert(desk.name);
console.log(desk.constructor);
alert(desk.run());
<script type="text/javascript">
// 寄生组合继承
function inherit(p){
if(p == null) throw TypeError();
if(Object.create){
return Object.create(p);
}
var t = typeof p;
if(t != "object" && t != "function") throw TypeError();
function F(){};
F.prototype = p;
return new F();
}
function inheritPrototype(subType, superType){
var prototype = Object(superType.prototype); //创建对象
prototype.contructor = subType; //增强对象
subType.prototype = prototype; //指定对象
}
function SuperType(name){
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
SuperType.prototype.sayName = function(){
console.log(this.name);
}
function SubType(name, age){
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
console.log(this.age);
}
var test = new SubType('ocean', 30);
console.log(test.colors);
test.sayName();
test.sayAge();
</script>