(三)创建对象

0.注

本文代码来自于《JavaScript高级程序设计》一书,非原创,算是小弟读书笔记。而且我也不认为自己写的实例代码能比Zakas的更清晰易懂。主要记录下自己认为干货的部分以及加入自己的理解。文中示意图等均为原创。

1.对象?

ECMA的定义:无序属性的集合,其属性可以包含基本值、对象或者函数。
我自己的理解,对象就是一个包含了若干键值对的无序列表。

2.创建对象的方式

  • 工厂模式(其实并没什么卵用)
    使用一个函数封装创建对象的全过程:创建一个临时对象、为这个对象添加属性、最后将这个对象返回
  //代码来自《JavaScript高级程序设计》
   function createPerson(name,age,job) {
       var o = new Object();
       o.name = name;
       o.age = age;
       o.job = job;
       o.sayName = function () {
           alert(this.name);
       };
       return o;
   }
   var person1 = createPerson('gordenZ','24','front-end engineer');
     ```

* 构造函数模式(问题也大,不会直接用)
  ```javascript
   //代码来自《JavaScript高级程序设计》
   function Person(name,age,job) {
       this.name = name;
       this.age = age;
       this.job = job;
       this.sayName = function () {
           alert(this.name);
       };
   }
   var person1 = new Person('gordenZ','24','front-end engineer');
     ```
这个例子中,创建了一个构造函数`Person`,并使用`new`操作符实例化了一个对象`person1`。
**为何要使用new 操作符?**
想像一下不使用new的情况:
```javascript
var person1 = Person('gordenZ','24','front-end engineer');
 console.log(name);//gordenZ

如果不使用new操作符,相当于在当前环境下直接执行Person这个函数(构造函数也是函数,仅仅是第一个字母大写了)。这里的执行环境是window,那么Person中的this就指向了全局的window对象,所以nameagejobsayName等属性都被创建在了全局对象上,可以直接被访问到。
new操作符干的事情
1.创建一个新对象
2.将构造函数的this指向这个对象(这样就不再是创建到window上了)
3.执行构造函数
4.返回新对象
其实跟工厂模式没有什么区别嘛
构造函数模式问题:
构造函数模式创建的每个对象的实例都是完全独立的,意味着每个实例中的属性都是不同的,这对于值是基本数据类型的属性来说还好,但是对于值是一个实现同一功能的函数的属性来说就显得冗余了,每一个实例都会有一个自己的函数,有多少个实例就会创建多少个相同的函数(不要忘了,每个函数都是一个对象)。

  • 原型模式
    js中每一个函数都有一个prototype(即原型)属性,指向一个对象,其功能是保存用这个函数类型创建的实例所共享的属性和方法。所以我们可以把需要在各个实例上共享的属性和方法放到这个类型的prototype中,即可只创建一次而被各实例所共享。
function Person() {
}
Person.prototype.name = "gordenZ";
Person.prototype.age = "24";
Person.prototype.job = "front-end engineer";
Person.prototype.sayName = function () {
    alert(this.name);
};
 var person1 = new Person();
 var person2 = new Person();

  console.log(person1.sayName === person2.sayName); //true

其中,Person构造函数Person.prototype原型对象person1person2Person实例,这三者的关系如下图:

构造函数、原型对象、实例之间的关系

每一个函数(也就包括了构造函数)在创建都会获得一个prototype属性,指向了这个函数的原型对象。所有的原型对象都默认有一个constructor·属性,指向构造函数(Person.prototype.constructor == Person //true)。在根据构造函数创建的实例中,有一个__proto__指针,指向了该类型的原型对象
可以看到,现在的nameagejobsayName被所有实例共享了。
1.每个实例又可以添加自己独立的属性

person1.sex = "man"

2.可以在实例中添加与原型中属性相同的属性,这样会屏蔽掉原型中的同名属性。寻找属性的方式是,首先在实例本身找,找到了就返回,如果没有找到,则到__proto__指针指向的原型对象上寻找。

person1.name = "grey"
console.log(person1.name) //grey 

3.其他实例若没有添加,则不受影响

console.log(person2.name) //gordenZ。

4.判断是原型属性还是实例属性:hasOwnProperty()

console.log(person1.hasOwnProperty('name'));//true
console.log(person2.hasOwnProperty('name'));//false

5.判断对象是否是一个实例的原型:isPrototypeOf()

console.log(Person.prototype.isPrototypeOf(person1));//true
console.log(Person.prototype.isPrototypeOf(person1));//true

6.获取一个实例的原型:Object.getPrototypeOf()

console.log(Object.getPrototypeOf(person1) == Person);//true

原型模式的问题
高度共享带来问题,在共享的属性中,如果是数据属性,可以用在实例上添加同名属性来屏蔽,但如果某个属性是一个引用类型,那么在任何一个实例上对其进行修改,都会影响到所有实例。

  • 组合使用构造函数模式和原型模式
    1.将每个实例自有的属性写在构造函数中,即实例属性
    2.将所有实例共享的方法写在原型对象中,即原型属性
    3.若直接使用对象字面量替换原型对象,需要将constructor属性补全
function Person(name,age,job) {
        this.name = name;
        this.age = age;
        this.job = job;
        this.friends = ["aa","bb"];
}
Person.prototype = {
    //补全constructor属性
    constructor:Person,
    sayName:function () {
       alert(this.name)
    }
};
var person1 = new Person();
var person2 = new Person();
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容