《JS高程》对象&原型学习笔记

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 操作符来调用,那它就跟普通函数也不会有什么两样。

// 当作构造函数使用
var person = new Person("Nick", 29, "Software Engineer");
person.sayName();    //"Nick"

// 作为普通函数调用
Person("Greg", 27, "Doctor");
window.sayName();    //"Greg"

//在另一个对象的作用域中调用
var o = new Object();
Person.call(o, "Kristen", 25, "Nurse");
o.sayName();    //"Kristen"

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

6.2.3 原型模式

我们创建的每个函数都有一个 prototype(原型)属性,该属性是一个指针,指向一个对象。

使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。

(1)理解原型对象

无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype 属性,这个属性指向函数的原型对象。在默认情况下,所有原型对象都会自动获得一个 constructor (构造函数)属性,该属性包含指向 prototype 属性所在函数的指针。

创建了自定义的构造函数之后,其原型对象默认只会取得 constructor 属性;至于其他方法,则都是从 Object 继承而来的。当调用构造函数创建一个新实例后,该实例的内部将包含一个指针([[Prototype]],内部属性),指向构造函数的原型对象。

在所有实现中都无法访问到[[Prototype]],可以通过 isPrototypeOf() 方法来确定对象之间是否存在实例和原型的关系:

alert(Person.prototype.isPrototypeOf(person1)); //true
alert(Person.prototype.isPrototypeOf(person2)); //true

ECMAScript 5 新增了一个新方法,叫 Object.getPrototypeOf(),返回 [[Prototype]] 的值:

alert(Object.getPrototypeOf(person1) === Person.prototype);    //true
alert(Object.getPrototypeOf(person1).name);    //"Nicholas"

使用 hasOwnProperty() 方法可以检测一个属性是存在于实例中,还是存在于原型中。这个方法(不要忘了它是从 Object 继承来的)只在给定属性存在于对象实例中时,才会返回 true。通过该属性,什么时候访问的是实例属性,什么时候访问的是原型属性就一清二楚了。

var person1 = new Person();
var person2 = new Person();

alert(person1.hasOwnProperty("name"));    //false

person1.name = "Greg";
alert(person1.name);    //"Greg"——来自实例
alert(person1.hasOwnProperty("name"));    //true

alert(person2.name);    //"Nicholas"——来自原型
alert(person2.hasOwnProperty("name"));    //false

delete person1.name;
alert(person1.name);    //"Nicholas"——来自原型
alert(person1.hasOwnProperty("name"));    //false

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

(2)原型与 in 操作符

有两种方式使用 in 操作符:单独使用和在 for-in 循环中使用。在单独使用时,in 操作符会在通过对象访问给定属性时返回 true,无论该属性存在于实例中还是原型中。

alert(person1.hasOwnProperty("name"));    //false;
alert("name" in person1);    //true

person1.name = "Greg";
alert(person1.name);    //"Greg"——来自实例
alert(person1.hasOwnProperty("name"));    //true
alert("name" in person1);    //true;

alert(person2.name);    //"Nicholas"——来自原型
alert(person2.hasOwnProperty("name"));    //false
alert("name" in person2);    //true;

delete person1.name;
alert(person1.name);    //"Nicholas"——来自原型
alert(person1.hasOwnProperty("name"));    //false
alert("name" in person1);    //true;

同时使用 hasOwnProperty() 方法和 in 操作符,就可以确定该属性到底是存在于对象中,还是存在于原型中。

function hasPrototypeProperty ( object, name ) {
    return !object.hasOwnProperty ( name ) && ( name in object );
}

在使用 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)更简单的原型语法

function Person(){
}

Person.prototype = {
   constructor : Person,
   name : "Nicholas",
   age : 29,
   job : "Software Engineer",
   sayName : function () {
       alert(this.name);
   }
};

注意:以这种方式重设 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
时间: 2024-10-08 13:43:33

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

《JS高程》事件学习笔记

事件:文档或浏览器窗口中发生的一些特定的交互瞬间,也即用户或浏览器自身执行的某种动作. ------------------------------------------------------------------------------------------------------------- 一.事件流 事件流:描述的是页面中接收事件的顺序. IE:事件冒泡流,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点(文档): NetScape:事件捕获流,即不太具体的节

js类、原型——学习笔记

js 内置有很多类,我们用的,都是从这些类实例化出来的. 1 function Object () {} 2 function Array () {} 3 function String () {} 4 function Boolean () {} 5 function Function () {} 比如,var a = {};等同于var a = new Object(); var a =[];等同于var a = new Array(); 现在我们要创建一个自定义的类.在SmartList.

Js脚本之jQuery学习笔记(1)

Js脚本之jQuery学习笔记(1) 一.javascript基础 单行注释 多行注释 /* */ 数据类型 数值型 字符串型 布尔型 空值 未定义值 转义字符 函数定义:1234567891011121314<head><script language="javascript"function test(m){var xixi="嘻嘻"alert("这是javascript")document.write(xixi + m)}

windows内核对象管理学习笔记

目前正在阅读毛老师的<windows内核情景分析>一书对象管理章节,作此笔记. Win内核中是使用对象概念来描述管理内核中使用到的数据结构.此对象(Object)均是由对象头(Object Header)组成,实际上由于对象头概念的特殊结构,还有些可选成分.于是一个对象实际上是分为三部分. OBJECT_HEADER对象头. 数据本体(比如文件对象File Object.Event等) 附加信息(比如Object Header Name Info等) 结构如下: //摘录自 Reactos代码

HTTP脚本化——XMLHttpRequest对象的学习笔记

一. HTTP 请求和响应 一个HTTP请求由4部分组成 HTTP请求方法(也叫动作Verb) 正在请求的URL 一个可选的请求头集合(可能包含身份验证信息等) 一个可选的请求主体 服务器返回的HTTP响应由3部分组成 一个数字和文字组成的状态码,用来显示请求的成功和失败 一个响应头集合 响应主体 说明: XMLHttpRequest不是协议级的HTTP API而是浏览器级的API,浏览器级的API需要考虑Cookie.重定向.缓存和代理,而协议级的API只需要考虑请求和响应 XMLHttpRe

js对象的学习笔记(仅供参考)

一.面向对象语言的基本特征: 抽象.封装.继承.多态 封装:将抽象的数据和对数据的操作封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作(成员方法),才能对数据进行操作 继承:由一个或多个类得来类的类的属性和方法的能力,一个类可以继承(extends)父类中的(public/protect)属性和(public/protect)方法,继承可以解决代码复用问题 多态:编写能以多种方法运行的函数或方法的能力 JS对象类型:本地对象.宿主对象(浏览器对象).内置对象 本地对象:独立于宿主

关于js的对象原型继承

javascript中,对象的继承是通过原型去继承. 可以这样理解:js中的对象,包含的除了属性和方法,还有一个最基本的原型__proto__对象.这个原型__proto__指向谁,这个对象就继承谁.这是最容易理解对象原型继承的一种方式. 如下面的代码: var student={ name:'zhangsan', age:21, run:function(){ return this.name+' is running!'; } }; var xiaoming={ name:'xiaoming

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

http://www.cppblog.com/besterChen/category/9573.html 所属分类: C/C++/STL/boost 在函数调用的时候,无论是参数为对象还是返回一个对象,都将产生一个临时对象.这个笔记就是为了学习这个临时对象的产生过程而写. 本代码的详细例子见实例代码Ex.01 Ok,先让我们定义一个类: class CExample { public: int m_nFirstNum; int m_nSecNum; int GetSum(); bool SetN

JS原型学习笔记

1.原型是函数对象的属性,它的初始值是一个空对象,这个prototype原型对象可以添加方法和属性. 2.构造器对象查找属性和方法时先查找构造器后查找原型. 3.若构造器中的属性和原型中的属性相同,构造器的优先级会高于原型. 4.枚举属性(for-in) (1).数组枚举 var a=[1,2,3]; for(var i in a){ console.log(a[i]); } (2).对象枚举 var a={name:"gao",age:"18",sex:"