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