原型对象

Author Avatar
Ninefire 6月 08, 2018
  • 在其它设备中阅读本文章

构造函数的修改

创建一个Person构造函数

  • 在Person构造函数中,为每一个对象都添加了一个sayName方法,并且sayName方法是在构造函数内部创建的,也就是说,构造函数每执行一次,就会创建一个新的sayName方法,创建10000个Person实例就会创建10000个sayName方法,即所有实例的sayName方法都是唯一的。这是完全没必要的,可以使所有的对象共享同一个方法。
function Person(name, age, gender){
    this.name = name;
    this.age = age;
    this.gender = gender;
    // 向对象中添加一个方法
    this.sayName = function(){
        alert('Hello,大家好,我是' + name + ',今年' + age + '岁了。');
    };
}

var per1 = new Person('李建刚',23,'女');
var per2 = new Person('赵打铁',22,'男');

console.log(per1.sayName == per2.sayName); // false
  • 将sayName方法在全局作用域中定义
// 在全局作用域中定义sayName
function sayName(){
    alert('Hello,大家好,我是' + name + ',今年' + age + '岁了。');
}

function Person(name, age, gender){
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.sayName = sayName;
}

var per1 = new Person('李建刚',23,'女');
var per2 = new Person('赵打铁',22,'男');

console.log(per1.sayName == per2.sayName); // true
  • 但是,将函数定义在全局作用域,污染了全局作用域的命名空间,而且定义在全局作用域中也很不安全。

原型对象

原型(prototype)

  • 我们创建的每一个函数,解析器都会向函数中添加一个属性prototype
    这个属性对应着一个对象,这个对象就是所谓的原型对象。
  • 如果函数作为普通函数调用,prototype没有任何作用,当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性__proto__指向该类(构造函数)的原型对象。
  • 原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中。
  • 当我们访问对象的某个属性或方法时,会先在对象自身中寻找,如果有则直接使用,如果没有则在原型对象中寻找,如果有则直接使用。
  • 创建构造函数时,可以将对象们共有的属性和方法,统一添加到构造函数的原型对象中,这种方式不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了。
function Person(name, age, gender){
    this.name = name;
    this.age = age;
    this.gender = gender;
}

// 添加sayName方法到Person类的原型对象中
Person.prototype.sayName = function(){
        alert('Hello,大家好,我是' + name + ',今年' + age + '岁了。');
};

var per1 = new Person('李建刚',23,'女');
var per2 = new Person('赵打铁',22,'男');
  • 使用in检查对象中是否含有某个属性时,如果对象中没有而原型对象中却存在,也会返回true
console.log('sayHello' in per1); // true
console.log('sayHello' in per2); // true
  • 可以使用对象的hasOwnProperty()方法来检查该对象自身中是否含有某属性,使用该方法只有当对象自身中含有该属性时,才会返回true。
console.log(per1.hasOwnProperty("sayHello")); // false
console.log(per2.hasOwnProperty("sayHello")); // false

原型链

  • 原型对象也是对象,所以它本身也有原型,当我们使用一个对象的属性或方法时,如果对象自身中存在则直接使用,否则将去原型对象中寻找,如果有则使用,否则将去原型对象的原型中寻找,以此类推直至Object对象的原型对象为止,Object对象的原型中的原型对象是null空,所以在Object的原型中依然没有找到则返回undefined
console.log(per1.hasOwnProperty("hasOwnProperty")); // false
console.log(per1.__proto__.hasOwnProperty("hasOwnProperty")); // false
console.log(per1.__proto__.__proto__.hasOwnPerty)); // true
console.log(per1.__proto__.__proto__.__proto__); // null

toString( )

  • 当直接在页面中打印一个对象时,实际上是输出的该对象的toString()方法的返回值,如果希望在输出对象时不为[object Object],可以为对象添加一个toString()方法来覆盖默认的方法。
// 创建一个Person类
function Person(name, age, gender){
    this.name = name;
    this.age = age;
    this.gender = gender;
}

// 创建两个Person类的实例
var per1 = new Person('李建刚',23,'女');
var per2 = new Person('赵打铁',22,'男');

// 直接打印两个实例
console.log(per1); // [object Object]
console.log(per2); // [object Object]

我们作如下更改:

function Person(name, age, gender){
    this.name = name;
    this.age = age;
    this.gender = gender;
}

// 修改Person类原型中的toString()方法
Person.prototype.toString = function(){
    return "Person[name=" + this.name + ", age=" + this.age + ", gender=" + this.gender + "]";
};

// 创建两个Person类的实例
var per1 = new Person('李建刚',23,'女');
var per2 = new Person('赵打铁',22,'男');

// 直接打印两个实例
console.log(per1); // [object Object]
console.log(per2); // [object Object]

垃圾回收(GC)

Garbage Collection

  • 程序运行过程中会产生垃圾,这些垃圾积攒过多以后,会导致程序运行的速度减慢,所以需要一个垃圾回收机制来处理程序运行过程中产生的垃圾。
  • 当一个对象没有任何的变量或者属性对它进行引用,此时将永远无法操作该对象,这个对象就是一个垃圾,这种对象过多时会占用大量的内存空间,导致程序运行变慢,所以这种垃圾必须进行清理。
  • 在JS中拥有自动垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行人工的垃圾回收操作。
  • 我们需要做的只是将不再使用的对象设置为null即可。

如发现错误请联系我,谢谢你。
本文链接:http://ninefire.tk/JavaScript.basics/14.html