JavaScript(15):对象和prototype继承
一、JavaScript 对象定义
所有 JavaScript 值,除了原始值,都是对象。
JavaScript 原始值
原始值指的是没有属性或方法的值。原始数据类型指的是拥有原始值的数据。
JavaScript 定义了 5 种原始数据类型:
- string
- number
- boolean
- null
- undefined
原始值是一成不变的(它们是硬编码的,因此不能改变)。
假设 x = 3.14,您能够改变 x 的值。但是您无法改变 3.14 的值。
JavaScript 对象
JavaScript 变量能够包含单个的值:
var person = "Bill Gates";
对象也是变量,但是对象能够包含很多值。值按照名称 : 值对的形式编写(名称和值以冒号分隔)。
var person = {firstName:"Bill", lastName:"Gates", age:62, eyeColor:"blue"};
JavaScript 对象是命名值的集合。
JavaScript 对象是被称为属性和方法的命名值的容器。
二、创建 JavaScript 对象
通过 JavaScript,您能够定义和创建自己的对象。
有不同的方法来创建对象:
- 定义和创建单个对象,使用对象文字。
- 定义和创建单个对象,通过关键词 new。
- 定义对象构造器,然后创建构造类型的对象。
在 ECMAScript 5 中,也可以通过函数 Object.create() 来创建对象。
1、使用对象字面量
这是创建对象最简答的方法。
使用对象文字,您可以在一条语句中定义和创建对象。
对象文字指的是花括号 {} 中的名称:值对(比如 age:62)。
下面的例子创建带有四个属性的新的 JavaScript 对象:
var person = {firstName:"Bill", lastName:"Gates", age:62, eyeColor:"blue"};
空格和折行不重要。对象定义可横跨多行:
var person = { firstName:"Bill", lastName:"Gates", age:62, eyeColor:"blue" };
2、使用 JavaScript 关键词 new
下面的例子也创建了带有四个属性的新的 JavaScript 对象:
var person = new Object(); person.firstName = "Bill"; person.lastName = "Gates"; person.age = 50; person.eyeColor = "blue";
上面的两个例子结果是一样的。无需使用 new Object()。
出于简易性、可读性和执行速度的考虑,请使用第一种创建方法(对象文字方法)。
注意:对象是易变的:它们通过引用来寻址,而非值。
如果 person 是一个对象,下面的语句不会创建 person 的副本:
var x = person; // 这不会创建 person 的副本。
对象 x 并非 person 的副本。它就是 person。x 和 person 是同一个对象。
对 x 的任何改变都将改变 person,因为 x 和 person 是相同的对象。
var person = {firstName:"Bill", lastName:"Gates", age:62, eyeColor:"blue"} var x = person; x.age = 10; // 这将同时改变 both x.age 和 person.age
注释:JavaScript 变量不是易变的。只有 JavaScript 对象如此。
3、使用JavaScript函数定义一个类型
function Aclass() { this.Property = 1; this.Method = function() { alert(1); } } var obj = new Aclass(); alert(obj.Property); obj.Method();
这个例子演示了通常的在JavaScript中定义一个类型的方法
三、JavaScript 对象属性
属性指的是与 JavaScript 对象相关的值。
属性是任何 JavaScript 对象最重要的部分。
JavaScript 对象是无序属性的集合。
属性通常可以被修改、添加和删除,但是某些属性是只读的。
1、访问 JavaScript 属性
访问对象属性的语法是:
bjectName.property // person.age
或者:
objectName["property"] // person["age"]
表达式必须计算为属性名。
person.firstname + " is " + person.age + " years old.";
person["firstname"] + " is " + person["age"] + " years old.";
2、JavaScript for...in 循环
JavaScript for...in 语句遍历对象的属性。
for...in 循环中的代码块会为每个属性执行一次。
循环对象的属性:
var person = {fname:"Bill", lname:"Gates", age:62}; for (x in person) { txt += person[x]; }
3、为实例对象添加或改变属性
为已有的对象添加新属性很简单:
myFather.nationality = "English";
新属性被添加到 myFather。不是 myMother,也不是任何其他 person 对象。
您不能使用预留词作为属性名(或方法名)。请使用 JavaScript 命名规则。
4、删除属性
delete 关键词从对象中删除属性:
var person = {firstName:"Bill", lastName:"Gates", age:62, eyeColor:"blue"}; delete person.age; // 或 delete person["age"];
delete 关键词会同时删除属性的值和属性本身。
删除完成后,属性在被添加回来之前是无法使用的。
delete 操作符被设计用于对象属性。它对变量或函数没有影响。
delete 操作符不应被用于预定义的 JavaScript 对象属性。这样做会使应用程序崩溃。
四、JavaScript 对象方法
JavaScript 方法是能够在对象上执行的动作。
JavaScript 方法是包含函数定义的属性。
1、this 关键词
在 JavaScript 中,被称为 this 的事物,指的是拥有该 JavaScript 代码的对象。
this 的值,在函数中使用时,是“拥有”该函数的对象。
请注意 this 并非变量。它是关键词。您无法改变 this 的值。
2、访问对象方法
请使用如下语法创建对象方法:
methodName : function() { 代码行 }
请通过如下语法来访问对象方法:
objectName.methodName()
您通常会把 fullName() 描述为 person 对象的方法,把 fullName 描述为属性。
fullName 属性在被通过 () 调用后会以函数形式执行。
此例访问 person 对象的 fullName() 方法:
name = person.fullName();
如果您访问 fullName 属性时没有使用 (),则将返回函数定义:
name = person.fullName;
3、为实例对象添加或改变方法
为已有的对象添加新方法很简单,新方法被添加到 myFather。不是 myMother,也不是任何其他 person 对象。
myFather.name = function () { return this.firstName + " " + this.lastName; };
改变实例对象的已有属性和方法。
function Aclass() { this.Property = 1; this.Method = function() { alert(1); } } var obj = new Aclass(); obj.Property = 2; obj.Method = function() { alert(2); } alert(obj.Property); obj.Method();
五、JavaScript 访问器(Getter 和 Setter)
ECMAScript 5 (2009) 引入了 Getter 和 Setter。
Getter 和 Setter 允许您定义对象访问器(被计算的属性)。
1、JavaScript Getter(get 关键词)
本例使用 lang 属性来获取 language 属性的值。
// 创建对象: var person = { firstName: "Bill", lastName : "Gates", language : "en", get lang() { return this.language; } }; // 使用 getter 来显示来自对象的数据: document.getElementById("demo").innerHTML = person.lang;
2、JavaScript Setter(set 关键词)
本例使用 lang 属性来设置 language 属性的值。
var person = { firstName: "Bill", lastName : "Gates", language : "", set lang(lang) { this.language = lang; } }; // 使用 setter 来设置对象属性: person.lang = "en"; // 显示来自对象的数据: document.getElementById("demo").innerHTML = person.language;
3、为什么使用 Getter 和 Setter?
- 它提供了更简洁的语法
- 它允许属性和方法的语法相同
- 它可以确保更好的数据质量
- 有利于后台工作
一个计数器实例
var obj = { counter : 0, get reset() { this.counter = 0; }, get increment() { this.counter++; }, get decrement() { this.counter--; }, set add(value) { this.counter += value; }, set subtract(value) { this.counter -= value; } }; // 操作计数器: obj.reset; obj.add = 5; obj.subtract = 1; obj.increment; obj.decrement; Object.defineProperty()
4、Object.defineProperty() 方法也可用于添加 Getter 和 Setter:
// 定义对象 var obj = {counter : 0}; // 定义 setters Object.defineProperty(obj, "reset", { get : function () {this.counter = 0;} }); Object.defineProperty(obj, "increment", { get : function () {this.counter++;} }); Object.defineProperty(obj, "decrement", { get : function () {this.counter--;} }); Object.defineProperty(obj, "add", { set : function (value) {this.counter += value;} }); Object.defineProperty(obj, "subtract", { set : function (value) {this.counter -= value;} }); // 操作计数器: obj.reset; obj.add = 5; obj.subtract = 1; obj.increment; obj.decrement;
六、JavaScript 对象构造器(构造函数)
创建一种“对象类型”的方法,是使用对象构造器函数。
在上面的例子中,函数 Person() 就是对象构造器函数。
通过 new 关键词调用构造器函数可以创建相同类型的对象:
var myFather = new Person("Bill", "Gates", 62, "blue"); var myMother = new Person("Steve", "Jobs", 56, "green");
1、为构造函数添加属性
如需向构造器添加一个新属性,您必须添加到构造器函数:
function Person(first, last, age, eyecolor) { this.firstName = first; this.lastName = last; this.age = age; this.eyeColor = eyecolor; this.nationality = "English"; }
这样对象属性就可以拥有默认值。
2、为构造函数添加方法
必须在构造器函数内部向一个对象添加方法:
function Person(firstName, lastName, age, eyeColor) { this.firstName = firstName; this.lastName = lastName; this.age = age; this.eyeColor = eyeColor; this.changeName = function (name) { this.lastName = name; }; }
changeName() 函数把 name 赋值给 person 的 lastName 属性。
myMother.changeName("Jobs");
通过用 myMother 替代 this,JavaScript 可以获知目前处理的哪个 person。
3、内建 JavaScript 构造函数
JavaScript 提供用于原始对象的构造器:
var x1 = new Object(); // 一个新的 Object 对象 var x2 = new String(); // 一个新的 String 对象 var x3 = new Number(); // 一个新的 Number 对象 var x4 = new Boolean(); // 一个新的 Boolean 对象 var x5 = new Array(); // 一个新的 Array 对象 var x6 = new RegExp(); // 一个新的 RegExp 对象 var x7 = new Function(); // 一个新的 Function 对象 var x8 = new Date(); // 一个新的 Date 对象
Math() 对象不再此列。Math 是全局对象。new 关键词不可用于 Math。
正如以上所见,JavaScript 提供原始数据类型字符串、数字和布尔的对象版本。但是并无理由创建复杂的对象。原始值快得多!
- 请使用对象字面量 {} 代替 new Object()。
- 请使用字符串字面量 "" 代替 new String()。
- 请使用数值字面量代替 Number()。
- 请使用布尔字面量代替 new Boolean()。
- 请使用数组字面量 [] 代替 new Array()。
- 请使用模式字面量代替 new RexExp()。
- 请使用函数表达式 () {} 代替 new Function()。
var x1 = {}; // 新对象 var x2 = ""; // 新的原始字符串 var x3 = 0; // 新的原始数值 var x4 = false; // 新的原始逻辑值 var x5 = []; // 新的数组对象 var x6 = /()/ // 新的正则表达式对象 var x7 = function(){}; // 新的函数对象
七、JavaScript 对象原型:prototype
构造函数创建的属性是实例私有的,原型创建的属性和方法是实例共享的。
1、在外部使用prototype为类型增加动态属性和方法
可以在外部使用prototype为自定义的类型添加属性和方法。 但是在外部不能通过prototype改变已有的自定义类型的属性或方法。
function Aclass() { this.Property = 1; this.Method = function() { alert(1); } }
Aclass.prototype.Property2 = 2; Aclass.prototype.Method2 = function() { alert(2); } var obj = new Aclass(); alert(obj.Property2); obj.Method2();
2、类型的继承(原型链)
所有 JavaScript 对象都从原型继承属性和方法。
日期对象继承自 Date.prototype。数组对象继承自 Array.prototype。Person 对象继承自 Person.prototype。Object.prototype 位于原型继承链的顶端,日期对象、数组对象和 Person 对象都继承自 Object.prototype。
这个例子说明了一个类型如何从另一个类型继承。
function AClass() { this.Property = 1; this.Method = function() { alert(1); } } function AClass2() { this.Property2 = 2; this.Method2 = function() { alert(2); } } AClass2.prototype = new AClass(); var obj = new AClass2(); alert(obj.Property); obj.Method(); alert(obj.Property2); obj.Method2();
3、子类如何重写父类的属性或方法
这个例子说明了子类如何重写父类的属性或方法。
function AClass() { this.Property = 1; this.Method = function() { alert(1); } } function AClass2() { this.Property2 = 2; this.Method2 = function() { alert(2); } } AClass2.prototype = new AClass(); AClass2.prototype.Property = 3; AClass2.prototype.Method = function() { alert(4); } var obj = new AClass2(); alert(obj.Property); obj.Method();
4、原型式继承
这种方法并没有使用严格意义的构造函数,而是借助原型可以基于已有的对象创建新对象,同时还不用创建自定义类型来达到这个目的。
以下代码是封装在object函数当中的,在使用的时候直接使用object()
function object (o)//这个o相当于父对象实例 { function F(){}//这个F相当子对象 F.prototype=o;//继承 return new F();//实例化传出 } var box = { //字面量对象 name: 'Lee', arr: ['哥哥', '妹妹', '姐姐'] }; var box1 = object (box); //传递 alert(box1.name);
box1.arr.push('父母');
var box2 = obj(box); //传递
alert(box2.name);
但是ECMAscript5定义了Object.create()方法,可以直接使用,他有俩个参数,下面来一个例子:
var person = { name: "Tom", age: 23, job: "web前端工程师" }; var anotherPerson = Object.create(person, { name: { value: "Mike" } }); alert(anotherPerson.name);
在上面这个例子中,create的第二参数是一个对象,其中的属性如果和person重名,则会覆盖person的属性。
5、借用构造函数实现继承
function SuperType() { this.colors = ["red", "blue", "green"]; } function SubType() { SuperType.call(this) //或者apply() } var instance1 = new SubType(); instance1.colors.push("black"); alert(instance1.colors); var instance2 = new SubType(); alert(instance2.colors);
借用构造函数也可以通过子对象向父对象传递参数
function SuperType(name) { this.name = name } function SubType() { SuperType.call(this, "Tom") //或者apply() } var instance1 = new SubType(); alert(instance1.name);
八、JavaScript ES5 对象方法
1、新的对象方法
Object.defineProperty(object, property, descriptor) // 添加或更改多个对象属性 Object.defineProperties(object, descriptors) // 访问属性 Object.getOwnPropertyDescriptor(object, property) // 以数组返回所有属性 Object.getOwnPropertyNames(object) // 以数组返回所有可枚举的属性 Object.keys(object) // 访问原型 Object.getPrototypeOf(object) // 阻止向对象添加属性 Object.preventExtensions(object) // 如果可将属性添加到对象,则返回 true Object.isExtensible(object) // 防止更改对象属性(而不是值) Object.seal(object) // 如果对象被密封,则返回 true Object.isSealed(object) // 防止对对象进行任何更改 Object.freeze(object) // 如果对象被冻结,则返回 true Object.isFrozen(object)
1、添加或更改属性值
Object.defineProperty(object, property, {value : value})
更改属性值:
var person = { firstName: "Bill", lastName : "Gates", language : "EN" }; // 更改属性 Object.defineProperty(person, "language", {value : "ZH"});
向对象添加新属性:
// 创建对象 var person = { firstName: "Bill", lastName : "Gates", language : "EN" }; // 添加属性 Object.defineProperty(person, "year", {value:"2008"});
ES5 允许更改以下属性元数据:
writable : true // 属性值可修改 enumerable : true // 属性可枚举 configurable : true // 属性可重新配置 writable : false // 属性值不可修改 enumerable : false // 属性不可枚举 configurable : false // 属性不可重新配置
ES5 允许更改 getter 和 setter:
// 定义 getter get: function() { return language } // 定义 setter set: function(value) { language = value }
此例使语言为只读:
Object.defineProperty(person, "language", {writable:false});
此例使语言不可枚举:
Object.defineProperty(person, "language", {enumerable:false});
添加 Getter 和 Setter
Object.defineProperty() 方法也可以用于添加 Getter 和 Setter:
// 创建对象 var person = {firstName:"Bill", lastName:"Gates"}; // 定义 getter Object.defineProperty(person, "fullName", { get : function () {return this.firstName + " " + this.lastName;} });
2、列出所有属性
此例列出对象的所有属性:
var person = { firstName: "Bill", lastName : "Gates" language : "EN" }; Object.defineProperty(person, "language", {enumerable:false}); Object.getOwnPropertyNames(person); // 返回属性数组
3、列出可枚举的属性
此例只列出对象的所有可枚举属性:
var person = { firstName: "Bill", lastName : "Gates" language : "EN" }; Object.defineProperty(person, "language", {enumerable:false}); Object.keys(person); // 返回可枚举属性的数组
posted on 2019-03-19 16:52 springsnow 阅读(250) 评论(0) 编辑 收藏 举报