原型对象
构造函数的修改
创建一个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