创建对象的藏宝线索

栏目: 后端 · 发布时间: 5年前

内容简介:关于我的疑问?为什么要用构造函数,用构造函数有什么好处?一直没有找到合适的答案,最后终于在红宝书中找到了线索!工厂模式创建的‘人’是没有灵魂的,因为他们不能识别创建他们的‘爸爸’,也就是alert(person1 instanceof createPerson);//false 这是因为o对象在createPerson函数中重新new Object()了,所以createPerson不是o的原型了而构造函数模式就解决了这个问题

关于我的疑问?为什么要用构造函数,用构造函数有什么好处?一直没有找到合适的答案,最后终于在红宝书中找到了线索!

function createPerson(name,age,sex){
    var o = {};
    o.name = name;
    o.age = age;
    o.sex = sex;
    o.sayName = function(){
        alert(this.name)
    }
}
var person1 = createPerson('小明',18,'女');
var person2 = createPerson('小西',20,'男');
复制代码

工厂模式创建的‘人’是没有灵魂的,因为他们不能识别创建他们的‘爸爸’,也就是alert(person1 instanceof createPerson);//false 这是因为o对象在createPerson函数中重新new Object()了,所以createPerson不是o的原型了

而构造函数模式就解决了这个问题

二、构造函数模式

function Person(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.sayName = function(){
        alert(this.name)
    }
}
var person1 = new Person('小明',18,'女');
var person2 = new Person('小西',20,'男');
复制代码

用这种new的方法创建出来的对象会自动获得一个constructor(构造函数)属性,这个属性,指向它的‘爸爸’,也就是Person。

构造函数虽然好用,但有一个缺点就是,在创建实例对象的时候,会把方法重新创建一遍。这会导致不同的作用域和标识符。alert(person1.sayName == person2.sayName)//false

** 解决办法:**

function Person(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.sayName = sayName
}
function sayName(){
    alert(this.name)
}
var person1 = new Person('小明',18,'女');
var person2 = new Person('小西',20,'男');
复制代码

把sayName函数作为全局函数,有一个指向函数Person的指针,person1和person2就可以访问同一个方法了。但这又会有一个新问题,sayName函数放在全局中,就能被其他对象调用,这是不太合理的,且不适用于封装。

这时候,原型模式就要登场了!

三、原型模式

在这个话题开始之前,我们应该先了解一下,property(原型):

了解property

1、每个函数都有property(原型)

2、每个对象都有_proto_(隐式原型)

3、对象是属性的集合,函数也是对象,所以函数既有property,又有_proto_

** 那么,prototy到底是什么呢?**

简单来说就是,把属性和方法添加到property(原型)上去,儿子们就可以通过一条线找到这些属性和方法,实现共享

function Person(){
}
Person.prototype.name = '小明';
Person.prototype.age = 18;
Person.prototype.sex = '女';
Person.prototype.sayName = function(){
    alert(this.name)
};

var person1 = new Person();
person1.sayName()//小明
var person2 = new Person();
//person2.sayName()//小明
复制代码

** 为什么‘儿子们’可以找到共享的方法呢? **

当创建一个函数爸爸的时候,会给爸爸一个prototype(原型)属性,这个属性会有一个constructor(自动得到的),这个属性会指向函数爸爸。也就是Person.prototype.constructo 指向 Person。

当创建了一个对象实例的时候,这个实例就会有一个_proto_(隐式原型),指向函数爸爸的prototype(原型)。这样说可能有点抽象,或许我们可以上个图!

创建对象的藏宝线索
  • Person.prototype指向原型对象
  • Person.prototype.constructor指回构造函数Person
  • person1和person2都有一个属性,指向原型对象
  • Person.prototype == person1(person2). proto

所以实现共享的本质是:当读取对象的属性时,1、看对象自己有没有这个属性或方法,如果找到了,就返回这个值 2、自己没有的话,就通 过_proto_ 指向的 prototype查找有没有这个属性或方法,如果有,就返回。

顺便附上作图工具:www.processon.com/

** 原型模式的缺点 **

  • 不能自定义参数
  • 属性是共享的,会对包含引用类型的值来说,产生致命问题
function Person(){}
Person.prototype={
    constructor : Person,
    name : '小明',
    age : 18,
    sex : '男',
    friends ; ["小花","小夏"],
    sayName : function(){
        alert(this.name)
    }
}
var person1 = new Person();
var person2 = new Person();

person1.friends.push(“小天”);
console.log(person1.friends);//"小花","小夏",“小天”
console.log(person2.friends);//"小花","小夏",“小天”
复制代码

由于person1修改的是Person.prototype,这个共享的属性,所以person2的值也会受影响

四、构造函数模式+原型模式

这种方法才是最目前运用最广泛的方法,因为这种方法取两种模式的有点,构造函数不共享,就用来定义实例的属性,原型模式共享,就用来定义实例的方法。

function Person(name,age,sex){
    this.name = name;
    this.age = age;
    this. sex = sex;
    this.friends = ["小花","小夏"];
}
var person1 = new Person('小明',18,'女');
var person2 = new Person('小西',20,'男');

person1.push("小天");
console.log(person1.friends);//"小花","小夏",“小天”
console.log(person2.friends);//"小花","小夏"
复制代码

以上所述就是小编给大家介绍的《创建对象的藏宝线索》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

计算机程序设计艺术・卷3

计算机程序设计艺术・卷3

[美] 高德纳(Donald E. Knuth) / 贾洪峰 / 人民邮电出版社 / 2017-2 / 198.00元

《计算机程序设计艺术》系列被公认为计算机科学领域的权威之作,深入阐述了程序设计理论,对计算机领域的发展有着极为深远的影响。本书为该系列的第3卷,全面讲述了排序和查找算法。书中扩展了卷1中数据结构的处理方法,并对各种算法的效率进行了大量的分析。一起来看看 《计算机程序设计艺术・卷3》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具