印象笔记迁移
面向对象函数
var box = new Object();box.name = 'dog';box.age = 20;box.run = function () { return this.name + this.age + 'gg';};alert(box.run());创建同样的object:
var box = new Object(); //方法1box.name = 'dog';box.age = 20;box.run = function () { return this.name + this.age + 'gg';};var box2 = new Object(); //代码繁杂box2.name = 'lv';box2.age = 18;box2.run = function () { return this.name + this.age + 'gg';};alert(box.run());alert(box2.run());var box = new Object();box.name = 'dog';box.age = 20;box.run = function () { return this.name + this.age + 'gg';};var box2 = box; //方法2box2.name = 'lv';box2.age = 18;box2.run = function () { return this.name + this.age + 'gg';};alert(box.run()); //会有重复alert(box2.run()); //结果box被box2覆盖解决多个类似对象声明的问题:
//工厂模式function createObject(name, age) { var obj = new Object(); //创建对象 obj.name = name; //添加属性 obj.age = age; obj.run = function () { //添加方法 return this.name + this.age + 'gg'; }; return obj; //返回对象引用}
var box1 = createObject('dog', '20'); //创建第一个对象var box2 = createObject('lv', '18'); //创建第二个对象alert(box1.run()); //dog20ggalert(box2.run()); //lv18gg2 collapsed lines
alert(box1 instanceof Object);alert(box2 instanceof Object); //他们都是object实例,无法分清到底是哪个object的实例//构造函数function Box(name, age) { //创建对象,所有构造函数的对象就是object this.name = name; //添加一个属性 this.age = age; this.run = function () { //添加方法 return this.name + this.age + 'gg'; }}
function Desk(name, age) { //创建对象,所有构造函数的对象就是object this.name = name; //添加一个属性 this.age = age; this.run = function () { //添加方法 return this.name + this.age + 'gg'; }22 collapsed lines
}
var box1 = new Box('dog', '20');var box2 = new Box('lv', '18');var box2 = new Desk('gg', 'gg');alert(box1.run());alert(box2.run());alert(box1 instanceof Object); //truealert(box1 instanceof Box); //truealert(box3 instanceof Box); //false,此时可以识别了解决了工厂模式的对象识别问题//1.构造函数没有new Object,但它会后台自动var obj = new Object//2.this就相当于obj//3.构造函数不需要返回对象引用,它是后台自动返回的
//规范://1. 构造函数也是函数,但函数名第一个字母大写//2.必须new 构造函数名,new Box()//3.必须使用new运算符alert(Box('dog', '20')); //构造函数用普通函数方式调用,无效var o = new Object();Box.call(o, 'dog', '20'); //对象冒充alert(o.run());原型(共享)
function Box() {}; //构造函数体内什么都没有,如果有,叫做实例属性,实例方法Box.prototype.name = 'dog';Box.prototype.age = 20;Box.prototype.run = function () { return this.name + this.age + 'gg';};var box1 = new Box();var box2 = new Box();alert(box1.name); //dogalert(box1.run()); //dog20gg//如果是实例方法,不同的实例化,他们的方法地址是不一样的,是唯一的//如果是原型方法,那么他们的地址是共享的alert(box1.run == box2.run); //truealert(box1.prototype); //这个属性是个对象,访问不到1 collapsed line
alert(box1.__proto__); //这个属性是一个指针指向prototype原型对象,ie不支持function Box() {};Box.prototype.name = 'dog';Box.prototype.age = 20;Box.prototype.run = function () { return this.name + this.age + 'gg';};var box1 = new Box();var box2 = new Box();alert(box1.constructor); //构造属性,可以获取构造函数本身//判断一个对象实例,是不是指向了对象的原型对象,基本上只要实例化了,他是自动指向的alert(Box.prototype.isPrototypeOf(box1));原型函数执行流程:
- 先查找构造函数实例里的属性或方法,如果就返回;
- 如果构造函数实例里没有,就去原型对象里找,如果有就返回;
function Box() {};Box.prototype.name = 'dog';Box.prototype.age = 20;Box.prototype.run = function () { return this.name + this.age + 'gg';};var box1 = new Box();box1.name = 'lv';alert(box1.name); //lvdelete box1.name; //删除实例中的属性alert(box1.name); //dogdelete Box.prototype.name; //删除原型中的属性Box.prototype.name = 'gg'; //覆盖原型中的属性var box2 = new Box();1 collapsed line
alert(box2.name); //dogfunction Box() {};Box.prototype.name = 'dog';Box.prototype.age = 20;Box.prototype.run = function () { return this.name + this.age + 'gg';};var box1 = new Box();box1.name = 'dog';alert(box1.hasOwnProperty('name')); //判断实例中是否存在指定属性alert('name in box1'); //不管实例属性或原型属性是否存在,只要有就返回true,都没有就返回falsefunction Box() {};Box.prototype.name = 'dog';Box.prototype.age = 20;Box.prototype.run = function () { return this.name + this.age + 'gg';};
//判断只有原型中有属性function isProperty(object, property) { return !object.hasOwnProperty(property) && (property in object);};var box1 = new Box();alert(isProperty(box1, 'name'));alert(box.prototype); //使用对象实例无法访问到prototypealert(box.__proto__); //使用对象实例访问prototype的指针alert(Box.prototype); //使用构造函数名(对象名)访问prototype,结合前面的图看使用字面量的方式创建原型对象:(new Object 相当于{})
Box.prototype = { //创建了一个新的对象 constructor: Box, //强制指向Box name: 'dog', age: 20, run: function () { return this.name + this.age + 'gg'; }}; //字面量创建的方式使用constructor属性不会指向实例,而会指向object,构造函数相反,除非强制指向原型声明被重写:
Box.prototype = { constructor: Box, name: 'dog', age: 20, run: function () { return this.name + this.age + 'gg'; }};Box.prototype = { //不会保留之前原型的任何信息.把原来的原型对象和构造函数的连接切断了 age: 18};var box = new Box();alert(box.age); //18alert(box.run()); //box.run is not a function其他类型的原型:
alert(Array.prototype.sort); //查看sort是否是Array原型对象里的方法alert(String.prototype.substr);扩展其他类型的原型:
alert(String.prototype.addstring); //undefined,检查String.prototype.addstring = function () { return this + ',被添加了';}var box = 'dog';alert(box.addstring()); //dog,被添加了原型的缺点:
function Box() {};Box.prototype = { constructor: Box, name: 'dog', age: 20, family: ['bro', 'sis'], run: function () { return this.name + this.age + 'gg'; }};var box1 = new Box();alert(box1.family); //bro,sisbox1.family.push('didi'); //在第一个实例修改后,保持了共享alert(box1.family); //bro,sis,didi2 collapsed lines
var box2 = new Box();alert(box2.family) //bro,sis,didi 共享了box1添加后的引用类型的原型解决构造传参和共享问题,可以组合构造函数+原型模式:
function Box(name, age) { //保持独立的用构造函数 this.name = name; this.age = age; this.family = ['bro', 'sis'];}
Box.prototype = { //保持共享的用原型 constructor: Box, run: function () { return this.name + this.age + 'gg'; }};var box1 = new Box('dog', 20);alert(box1.run()); //dog20ggvar box2 = new Box('lv', 18);4 collapsed lines
alert(box2.run()); //lv18ggbox1.family.push('didi');alert(box1.family); //bro ,sis,didialert(box2.family); //bro,sis动态原型模式:封装构造函数和原型模式:
function Box(name, age) { this.name = name; this.age = age; this.family = ['bro', 'sis']; alert('初始化开始'); Box.prototype.run = function () { return this.name + this.age + 'gg'; }; alert('初始化结束');}
var box1 = new Box();var box2 = new Box(); //alert执行四次,然而原型初始化只要第一次初始化就可以了,没必要每次构造函数实例化的时候都初始化function Box(name, age) { this.name = name; this.age = age; this.family = ['bro', 'sis']; if (typeof this.run != 'function') { //判断this.run是否存在 alert('初始化开始'); Box.prototype.run = function () { return this.name + this.age + 'gg'; }; alert('初始化结束'); }}
var box1 = new Box();var box2 = new Box(); //只初始化一次寄生构造函数 = 工厂模式 + 构造函数
function Box(namem, age) { var obj = new Object(); obj.name = name; obj.age = age; obj.run = function () { this.name + this.age + 'gg'; }; return obj;}var box1 = new Box('dog', 20);稳妥构造函数:
function Box(name, age) { var obj = new Object(); obj.name = name; obj.age = age; obj.run = function () { this.name + this.age + 'gg'; }; return obj;}
var box1 = Box('dog', 20); //不用new继承
,不支持接口实现,而实现继承的方法是依靠原型链function Box() { //被继承的函数叫做超类型(父类,基类) this.name = 'dog';}
function Desk() { //继承的函数叫做子类型(子类,派生类) this.age = 20;}
function Table() { this.level = 'aa';}
var desk = new Desk();alert(desk.age); //20alert(desk.name); //undefined5 collapsed lines
//通过原型链继承,超类型实例化后的对象实例,赋值给子类型的原型属性//new Box()会将Box构造里的信息和原型里的信息都交给Desk//Desk的原型,得到的是Box的构造和原型里的信息Desk.prototype = new Box();Table.prototype = new Desk();
继承中的小细节
function Box() { this.name = 'dog';}
Box.prototype.name = 'lv'
function Desk() { this.age = 20;}
Desk.prototype = new Box();var desk = new Desk();alert(desk.name); //dog,就近原则,先实例,后原型//子类型从属于自己或者他的超类型alert(desk instanceof Desk); //true4 collapsed lines
alert(desk instanceof Box); //truealert(desk instanceof Object);truealert(Box instanceof Desk); //false解决引用共享和超类型无法传参的问题:(对象冒充):
function Box(name, age) { this.name = name; this.age = age; this.family = ['bro', 'sis'];}
Box.prototype.family = 'home';
function Desk(name, age) { Box.call(this, name, age); //对象冒充,只能继承构造里的信息.原型里的不行}
var desk = new Desk('dog', 20);alert(desk.name);alert(desk.family);1 collapsed line
alert(desk.fanily);原型式继承:
function obj(o) { //临时中转函数 function F() { }; //F构造是个临时新建的对象,用来存储传递过来的对象 F.prototype = o; //将o对象实例赋值给F构造的原型对象 return new F(); //最后返回这个得到传递过来对象的对象实例}
var box = { //这是字面量的声明方式,相当于var box = new Box(); name: 'dog', age: 20, family: ['bro', 'sis']};//box1就等于new F()var box1 = obj(box);alert(box1.name);5 collapsed lines
alert(box1.family);box1.family.push('didi');alert(box1.family);var box2 = obj(box);alert(box2.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 + 'gg'; };}
var box = {6 collapsed lines
name: 'dog', age: 20, family: ['bro', 'sis']};var box1 = create(box);alert(box1.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;15 collapsed lines
this.age = age;}
function Desk(name, age) { Box.call(this, name, age); //对象冒充}
Box.prototype.run = function () { return this.name + this.age + 'gg';}//通过寄生组合继承来实现继承create(Box, Desk);var desk = new Desk('lv', 18);alert(desk.run());alert(desk.constructor);