码迷,mamicode.com
首页 > 编程语言 > 详细

javascript面向对象和原型————呱呱二号

时间:2018-01-09 00:19:00      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:efi   工厂   define   理解   访问   对象   自己   直接   知识   

面向对象

1、工厂模式

function createObject(name,age){
  let obj = new Object();
  this.name = name;
  this.age = age;
  return obj;            
}
let objA = createObject(‘Tom‘,24);
let objB = createObject(‘Jane‘,23);
typeof ObjA;    //Object
typeof ObjB;    //Object
ObjA instanceof Object;
ObjA instanceof Object;
//方法缺点:不能区分对象实例,所有对象实例都由Object实例化

2、构造函数模式

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;
  }       
}
let box = new Box(‘Tom‘,24);
let desk = new Desk(‘Jane‘,23);
box instanceof Box;  //true
box instanceof Desk;  //false
desk instanceof Desk;  //true
//
//知识延伸,对象冒充
let o = new Object();
Box.call(o,‘Ha‘,25);
o.name;

构造函数方式和原型方式变量存储的方式

技术分享图片

技术分享图片

 3、原型

  我们创建的每一个函数都有一个prototype(原型属性),这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法。逻辑上可以这么理解:prototype通过调用构造函数而创建的那个对象的原型对象。使用原型的好处可以让所有对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中定义对象信息,而是可以直接将这些信息添加到原型中。(我自己的理解,通过构造函数创建的对象会自动创建一个原型对象prototype。)

function Box(){}

Box.prototype.name = ‘Lee‘;  //原型属性

Box.prototype.age = 100;

Box.prototype.run = function () {  //原型方法

  return this.name + this.age + ‘运行中‘;

}

证明:原型对象内的属性和方法都被实例对象共用

let box1 = new Box();

let box2 = new Box();

Object.is(box1.run,box2.run);  //true  Object.is(),判断两个变量是否相等 (等于box1.run === box2.run);

说明box1和box2中的run方法都指向同一个引用地址。

技术分享图片

在原型模式声明中,多了两个属性,这两个属性都是创建对象时自动生成的。__proto__属性是实例指向原型对象的一个指针,它的作用就是指向构造函数的原型属性constructor。通过这两个属性,就可以访问到原型里的属性和方法了。

//判断一个实例对象是否指向了原型对象,只要实例化了,会自动指向的

Box.prototype.isPrototypeOf(box1);  //true    接着上面的代码

let obj = new Object();  //

Box.prototype.isPrototypeOf(obj);

 

如果实例对象中有name属性,原型对象中也有name属性,通过 . 访问name会打印处实例对象中的name属性。

function Box () {}

Box.prototype.name = ‘guaguaerhao‘;

let box1 = new Box();

box1.name = ‘呱呱二号‘;

console.log(box1.name);  //呱呱二号

原型模式的执行流程:

1、先查找实例对象中是否存在属性,如果存在,则返回

2、如果实例对象中没有该属性,则在原型对象中查找,如果存在,则返回

 判断实例中是否存在属性

box1.hasOwnProperty(‘name‘);  //true

(name in box1)  //不管是原型中有name属性还是实例中有name属性,都会返回true

判断只有原型中是否存在属性

function hasPrototypeProperty(object,property){

  return !object.hasOwnProperty(property) && (property in object);

}

4、字面量原型模式

function Box () {}

Box.prototype = {

  constructor: Box,  //将原型对象的constructor强制指向回Box

  name: ‘guaguaerhao‘,

  age: 24,

  run: function(){

    return this.name + this.age;

  }

}

 ps:原型中最大的缺点就是它的优点,共享。原型模式创建的对象,省略了构造函数传参,带来的缺点就是初始化的值都是一样的。

 5、构造函数加原型模式(构造函数和方法分开,没有一种封装的感觉,感觉很零碎)

function Box(name,age){    //不共享的使用构造函数

  this.name = name;

  this.age = age;

  this.family = [‘爸爸‘,‘妈妈‘,‘哥哥‘,‘我‘];

}

 Box.prototype = {    //共享的使用原型

  constructor: Box,

  run: function () {

    return this.name + this.age;

  }

}

6、动态原型模式

 function Box(name,age){

  this.name = name;

  this.age = age;

  //可是,实例化对象的时候,每次都会创建run()方法,浪费内存,因为他在每一个对象中都是一样的功能,没有必要,每次实例化都创建,实际上只需要创建一次。

  Box.prototype.run = function () {

    return this.name + this.age;

  }

}

所以

function Box(name,age){

  this.name = name;

  this.name = age;

  if(typeof this.run !== ‘function‘){  //只会实例化一次

    Box.prototype.run = function () {

      return this.name + this.age;

    }

  }

}

7、寄生构造函数(工厂模式+构造函数)

function Box(name,age){

  let obj = new Object();

  obj.name = name;

  obj.age = age;  

  obj.run = function (){

    return this.name + this.age;

  }

  return obj;

}

let obj = new Box(‘ha‘,24);

obj.run();

7、寄生构造函数(工厂模式+构造函数)

function Box(name,age){

  let obj = new Object();

  obj.name = name;

  obj.age = age;  

  obj.run = function (){

    return this.name + this.age;

  }

  return obj;

}

let obj = Box(‘ha‘,24);

obj.run();

 继承

1、继承是面向对象中比较核心的概念,ECMAScript只支持继承:

技术分享图片

function Parent(){

  this.name = ‘p‘;

}

function Child(){

  this.name = ‘c‘;

}

//通过原型链继承,父类实例化后的对象实例,赋值给子类型的原型属性

//new Parent()会将构造函数里的信息和原型的信息都交给Child

Child.prototype = new Parent();

2、对象冒充模式

为了解决引用共享和超类型无法传参的问题,采用一种叫借用构造函数的技术,或者成为对象冒充

function Parent(name,age){

  this.name = name;

  this.age = age;

}

//Parent.prototype.family = ‘家庭‘;  //child实例无法访问

function Child(name,age){

  Parent.call(this,name,age);  //对象冒充,给父类传递参数,对象冒充只能继承构造函数中的属性,原型中的无法访问

}

let child = new Child(‘haha‘,24);

child.name;

child.family;  //undefined

3、原型链加借用构造函数,组合模式

function Parent(age){

  this.age = age;

}

Parent.prototype.run = function () {  //解决了方法共享

  return this.age;

}

function Child(age){

  Parent.call(this,age);

}

Child.prototype = new Parent();

javascript面向对象和原型————呱呱二号

标签:efi   工厂   define   理解   访问   对象   自己   直接   知识   

原文地址:https://www.cnblogs.com/guaguaerhao/p/8214038.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!