Javascript对象练习
2017-10-09 本文已影响0人
Zerxoi
1.对象构造函数的创建及实例化
/* 创建对象的属性在构建造函数中声明 */
function Person(first, last, age, gender){
this.name = {
first:first,
last:last
}
this.age = age;
this.gender = gender;
}
/* 性能考量
如果不是因为某些特殊任务而需要闭包,在没有必要的情况下,在其它函数中创建函数是不明智的,因为闭包对脚本性能具有负面影响,包括处理速度和内存消耗。
例如,在创建新的对象或者类时,方法通常应该关联于对象的原型,而不是定义到对象的构造器中。原因是这将导致每次构造器被调用,方法都会被重新赋值一次(也就是说,为每一个对象的创建)。
参见:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures */
/* 创建对象的方法在对象的原型对象(prototype属性)中添加 */
Person.prototype.greeting = function(){
alert('Hello,I\'m ' + this.name.first + ' ' + this.name.last);
};
/* 实例化 */
/* 当一个函数用作构造函数时(使用new关键字),它的this被绑定到正在构造的新对象。 */
marry = new Person('Marry', 'Jane', '23', 'female');
/* 测试 */
marry.name.first; // "Marry"
marry.greeting(); // [Hello,I'm Marry Jane]
一个类的基本属性应该在创建之前就想好,并且都应该放置在构造函数中。因为创建好的构造函数无法动态修改,如果要想给类A的构造函数添加新的属性,那还是创建一个类A的子类吧。
那么为什么类的方法要在类的原型对象中定义呢。
/* 在上述构造函数基础上,要如何才能获取对象的全名(fullname)呢? */
/* 一方面是上面所说的 性能考量 */
/* 另一方面,如果我希望每个Person类的实例都能获取全名的话,就要在prototype中添加咯,毕竟构造函数没法修改 */
/* 试想1.直接用fullname属性获取对象全名 */
Perosn.prototype.fullname = this.name.first + ' ' + this.name.last; // 调用fullname属性时,this绑定在window,并不是目标对象。
/* 测试 */
marry.fullname; // "undefined undefined"
/* 试想2.使用方法获取对象全名 */
Person.prototype.fullname = function(){
return this.name.first + ' ' + this.name.last;
}; // 很明显,试想2成功了,因为在函数中的this绑定在目标对象上
/* 测试 */
marry.fullname(); // "Marry Jane"
2.对象的继承
/* 原型链继承测试 */
marry.__proto__===Person.prototype;
/* 属性的继承 */
/* 这里使用了Function.call(),第一个参数指明了在你运行这个函数时想对“this”指定的值,也就是说,你可以重新指定你调用的函数里所有“this”指向的对象。其他的变量指明了所有目标函数运行时接受的参数。
再加之,new创建新对象时,将this绑定到新创建的对象。所以属性的继承到此结束*/
function Student(first, last, age, gender, grade, school){
Person.call(this,first, last, age, gender);
this.grade = grade;
this.school = school;
}
/* 测试 */
tom.name; // {first: "Tom", last: "Smith"}
tom.grade; // 3
tom.greeting(); // Uncaught TypeError
/* 方法的继承 */
/* Javascript的继承是基于原型链的,方法和属性首先会在对象中搜索,如果没有搜索到则会到对象的原型对象的prototype中搜索,直到找到或者找不到而终止。
参见:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
prototype 属性的值是一个对象,我们希望被原型链下游的对象继承的属性和方法,都被储存在其中。 */
/* 这里使用的Object.create()函数,以Person.prototype的为原型创建一个新的对象 */
Student.prototype = Object.create(Person.prototype);
/* 因为constructor属性指向对象的构造器函数,所以Person.prototype的constructor指向的是Person,这里应该修改成Student,以避免在以后的使用中发生错误。 */
Student.prototype.constructor = Student;
/* 原型链继承测试 */
tom.__proto__.__proto__ === Person.prototype;
tom.__proto__ === Student.prototype;