ECMA-262 把对象定义为:”无序属性的集合,其属性可以包含基本值、对象或者函数。”可以把 ECMAScript 的对象想象成散列表:无非就是一组名值对,其中值可以是数据或函数。
 
6.1.理解对象
创建自定义对象的两种方式:
(1)创建一个 Object 的实例:  var person = new Object(); 
(2)对象字面量(首选):  var person = {};  
---------------------------------------------------------------------------------------------
ECMAScript 中有两种属性:数据属性和访问器属性。
数据属性包含一个数据值的位置。
    要修改属性默认的特性,必须使用 ECMAScript 5 的 Object.defineProperty() 方法。
访问器属性不包含数据值,它们包含一对 getter 和 setter 函数。
    访问器属性不能直接定义,必须使用 Object.defineProperty() 来定义。
    __year:year 前面的下划线是一种常用的标记,表示只能通过对象方法访问。
----------------------------------------------------------------------------------------------
定义多个属性:Object.defineProperties() 方法,可同时定义数据属性和访问器属性。
----------------------------------------------------------------------------------------------
读取属性的特性:Object.getOwnPropertyDescriptor() 方法,可以取得给定属性的描述符。
 
6.2.创建对象
6.2.2 构造函数模式
构造函数与其他函数的唯一区别,就在于调用它们的方式不同。任何函数,只要通过 new 操作符来调用,那它就可以作为构造函数;而任何函数,如果不通过 new 操作符来调用,那它就跟普通函数也不会有什么两样。
  1. // 当作构造函数使用
  2. var person = new Person("Nick", 29, "Software Engineer");
  3. person.sayName(); //"Nick"
  4.  
  5. // 作为普通函数调用
  6. Person("Greg", 27, "Doctor");
  7. window.sayName(); //"Greg"
  8.  
  9. //在另一个对象的作用域中调用
  10. var o = new Object();
  11. Person.call(o, "Kristen", 25, "Nurse");
  12. o.sayName(); //"Kristen"

构造函数的主要问题:每个方法都要在实例上重新创建一遍,因为 ECMAScript 中的函数是对象,因此每定义一个函数,也就实例化了一个对象。

6.2.3 原型模式
我们创建的每个函数都有一个 prototype(原型)属性,该属性是一个指针,指向一个对象。
使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。
(1)理解原型对象
    无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype 属性,这个属性指向函数的原型对象。在默认情况下,所有原型对象都会自动获得一个 constructor (构造函数)属性,该属性包含指向 prototype 属性所在函数的指针。
    创建了自定义的构造函数之后,其原型对象默认只会取得 constructor 属性;至于其他方法,则都是从 Object 继承而来的。当调用构造函数创建一个新实例后,该实例的内部将包含一个指针([[Prototype]],内部属性),指向构造函数的原型对象。
在所有实现中都无法访问到[[Prototype]],可以通过 isPrototypeOf() 方法来确定对象之间是否存在实例和原型的关系:
  1. alert(Person.prototype.isPrototypeOf(person1)); //true
  2. alert(Person.prototype.isPrototypeOf(person2)); //true
ECMAScript 5 新增了一个新方法,叫 Object.getPrototypeOf(),返回 [[Prototype]] 的值:
  1. alert(Object.getPrototypeOf(person1) === Person.prototype); //true
  2. alert(Object.getPrototypeOf(person1).name); //"Nicholas"
使用 hasOwnProperty() 方法可以检测一个属性是存在于实例中,还是存在于原型中。这个方法(不要忘了它是从 Object 继承来的)只在给定属性存在于对象实例中时,才会返回 true。通过该属性,什么时候访问的是实例属性,什么时候访问的是原型属性就一清二楚了。
  1. var person1 = new Person();
  2. var person2 = new Person();
  3.  
  4. alert(person1.hasOwnProperty("name")); //false
  5.  
  6. person1.name = "Greg";
  7. alert(person1.name); //"Greg"——来自实例
  8. alert(person1.hasOwnProperty("name")); //true
  9.  
  10. alert(person2.name); //"Nicholas"——来自原型
  11. alert(person2.hasOwnProperty("name")); //false
  12.  
  13. delete person1.name;
  14. alert(person1.name); //"Nicholas"——来自原型
  15. alert(person1.hasOwnProperty("name")); //false

ECMAScript 5 的 Object.getOwnPropertyDescriptor() 方法只能用于实例属性,要取得原型属性的描述符,必须直接在原型对象上调用 Object.getOwnPropertyDescriptor() 方法。

(2)原型与 in 操作符
有两种方式使用 in 操作符:单独使用和在 for-in 循环中使用。在单独使用时,in 操作符会在通过对象访问给定属性时返回 true,无论该属性存在于实例中还是原型中。
  1. alert(person1.hasOwnProperty("name")); //false;
  2. alert("name" in person1); //true
  3.  
  4. person1.name = "Greg";
  5. alert(person1.name); //"Greg"——来自实例
  6. alert(person1.hasOwnProperty("name")); //true
  7. alert("name" in person1); //true;
  8.  
  9. alert(person2.name); //"Nicholas"——来自原型
  10. alert(person2.hasOwnProperty("name")); //false
  11. alert("name" in person2); //true;
  12.  
  13. delete person1.name;
  14. alert(person1.name); //"Nicholas"——来自原型
  15. alert(person1.hasOwnProperty("name")); //false
  16. alert("name" in person1); //true;
同时使用 hasOwnProperty() 方法和 in 操作符,就可以确定该属性到底是存在于对象中,还是存在于原型中。
  1. function hasPrototypeProperty ( object, name ) {
  2. return !object.hasOwnProperty ( name ) && ( name in object );
  3. }
在使用 for-in 循环时,返回的是所有能够通过对象访问的、可枚举的(enumerated)属性,其中既包括存在于实例中的属性,也包括存在于原型中的属性。屏蔽了原型中不可枚举属性(即将 [[Enumerable]] 标记为 false 的属性)的实例属性也会在 for-in 循环中返回,因为根据规定,所有开发人员定义的属性都是可枚举的。
不可枚举的属性和方法:hasOwnProperty()、propertyIsEnumerable()、toLocaleString()、toString()、valueOf()、constructor、prototype
取得对象上所有可枚举的实例属性,可以使用 ECMAScript 5 的 Object.keys() 方法。
如果想要得到所有实例属性,无论它是否可枚举,都可以使用 Object.getOwnPropertyNames() 方法。
Object.keys() 和 Object.getOwnPropertyNames() 方法都可以用来替代 for-in 循环。
(3)更简单的原型语法
  1. function Person(){
  2. }
  3.  
  4. Person.prototype = {
  5. constructor : Person,
  6. name : "Nicholas",
  7. age : 29,
  8. job : "Software Engineer",
  9. sayName : function () {
  10. alert(this.name);
  11. }
  12. };

注意:以这种方式重设 constructor 属性会导致它的 [[Enumerable]] 特性被设置为 true。默认情况下,原生的 constructor 属性是不可枚举的。

6.2.4 组合使用构造函数模式和原型模式
    创建自定义类型的最常见方式,就是组合使用构造函数模式与原型模式。构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。另外,这种混成模式还支持向构造函数传递参数;可谓是集两种模式之长。
  1. function Person(name, age, job) {
  2. this.name = name;
  3. this.age = age;
  4. this.job = job;
  5. this.friends = ["Shelby", "Court"];
  6. }
  7.  
  8. Person.prototype = {
  9. constructor : Person,
  10. sayName : function() {
  11. alert(this.name);
  12. }
  13. }
  14.  
  15. var person1 = new Person("Nicholas", 29, "Software Enginner");
  16. var person2 = new Person("Greg", 27, "Doctor");
  17.  
  18. person1.friends.push("Van");
  19. alert(person1.friends); //"Shelby, Court, Van"
  20. alert(person2.friends); //"Shelby, Court"
  21. alert(person1.friends === person2.friends); //false
  22. alert(person1.sayName === person2.sayName); //true

参考文章:深入解读JavaScript面向对象编程实践

JS核心系列:浅谈 原型对象和原型链

A Plain English Guide to JavaScript Prototypes

《JS高程》对象&原型学习笔记的更多相关文章

  1. 《JS高程》事件学习笔记

    事件:文档或浏览器窗口中发生的一些特定的交互瞬间,也即用户或浏览器自身执行的某种动作. -------------------------------------------------------- ...

  2. 《JS高程》数据类型学习笔记

    认认真真看完了<JavaScript高级程序设计>第3章的基本概念,原来一直不明白的知识点都在这里面啊...T_T...基础真的很重要,很重要,很重要... 现在终于明白了读书的技巧,书读 ...

  3. js类、原型——学习笔记

    js 内置有很多类,我们用的,都是从这些类实例化出来的. function Object () {} function Array () {} function String () {} functi ...

  4. 《JS高程》引用类型学习笔记

    2月圆满的结束了,结束之前是如凤凰般的涅槃.一边上班,一边搞科研的忙碌有点让人透不过气,心会不由得浮躁起来.但是,无论什么事情,只要充满耐心.专心去做,总会朝好的方向发展,心态真的很重要.Anyway ...

  5. 《Node.js核心技术教程》学习笔记

    <Node.js核心技术教程>TOC \o "1-3" \h \z \u 1.章模块化编程 2019.2.19 13:30' PAGEREF _101 \h 1 08D ...

  6. JavaScript原型学习笔记

    1 理解JavaScript原型 什么是原型? 原型是一个对象,其他对象可以通过它实现属性继承. 任何一个对象都可以成为原型么? 是 哪些对象有原型 所有的对象在默认的情况下都有一个原型,因为原型本身 ...

  7. C++中临时对象的学习笔记

    http://www.cppblog.com/besterChen/category/9573.html 所属分类: C/C++/STL/boost  在函数调用的时候,无论是参数为对象还是返回一个对 ...

  8. 关于js的对象原型继承(一)

    javascript中,对象的继承是通过原型去继承. 可以这样理解:js中的对象,包含的除了属性和方法,还有一个最基本的原型__proto__对象.这个原型__proto__指向谁,这个对象就继承谁. ...

  9. 深度剖析前端JavaScript中的原型(JS的对象原型)

          这张图片有点劝退了,哈哈哈~    通过原型机制,JavaScript 中的对象从其他对象继承功能特性:这种继承机制与经典的面向对象编程语言的继承机制不同.本文将探讨这些差别,解释原型链如 ...

随机推荐

  1. 解决Putty连接不上服务器的方法

    1.vi /etc/ssh/sshd_config 将PermitRootLogin的注释取消,或者将no改为yes. 2.service sshd restart 3.setup命令进入将防火墙关闭 ...

  2. PHP+socket游戏数据统计平台发包接包类库

    <?php /** * @title: PHP+socket游戏数据统计平台发包接包类库 * @version: 1.0 * @author: perry <perry@1kyou.com ...

  3. 谷歌官方SwipeRefreshLayout下拉刷新的用法。

    <Android SwipeRefreshLayout:谷歌官方SDK包中的下拉刷新> 下拉刷新在如今移动开发中应用如此广泛和普遍,以至于谷歌干脆在SDK中给予支持.在android-su ...

  4. Code First Migrations更新数据库结构的具体步骤

    一.打开程序包管理器控制台 当你的实体模型与数据库架构不一致时,引发以下错误:The model backingthe 'SchoolContext' context has changed sinc ...

  5. 精华 ionic入门之色彩、图标、边距和界面组件:列表

    目录:色彩.图标和边距色彩图标内边距界面组件:列表列表:.list成员容器:.item.item: 嵌入文本.item : 嵌入图标.item : 嵌入头像.item : 嵌入缩略图.item : 嵌 ...

  6. lucene 过滤结果

    package cn.itcast.h_filter; import java.util.ArrayList; import java.util.List; import org.apache.luc ...

  7. Linux的三种特殊权限

    1.Suid Set位权限 ●对文件以文件的拥有者身份执行文件 ●对目录无影响 权限设置: ●suid=u+s 2.Sgid Set位权限 ●对文件以文件的组身份执行文件 ●对目录在目录中最新创建的文 ...

  8. 分布式一致性原理—BASE

    定义 BASE是BasicallyAvailable(基本可用).Soft state(软状态)和Eventually consistent(最终一致性)三个短语的简写,是由来自eBay的架构师Dan ...

  9. IBInspectable / IBDesignable

    无论陈词滥调多少次,比起一个需要我们记住并且输入什么的界面来说,如果替换成我们能够看见并可控制的界面的话将会是巨大的进步. Xcode 6 提供了这样一个替代,在旧技术上建立新的互动.在设计项目的时候 ...

  10. vi编辑器选项

    Vi编辑器有一些选项设置可以帮助人们更好的使用. 在vi中选项分为两种: 1.  开关选项,如果要打开这类选项就使用ex命令——:set 选项:如果要关闭这类选项就是用ex命令——:set  no选项 ...