原型
每个构造方法中都有一个属性prototype,这个属性指向了一个对象,这个对象中保存的是通过该构造方法创建出来的所有实例可以共享的内容。我们把这个对象就称为原型对象,简称原型。简单点说,所谓原型就是对象公用内容的集合体。(静态属性,方法)
注意事项
原型对象是随着构造函数的创建而创建,原型的创建时间早于对象
默认情况下,原型对象为一个“空对象”
原型对象中保存的是实例化对象所共有的属性和方法
添加原型属性
构造方法.prototype.属性名 = 属性值;
删除原型属性
delete 构造方法.prototype.属性名;
修改原型属性
构造方法.prototype.属性名 = 新值;
获取原型属性
构造方法.prototype.属性名;
实例化对象.原型属性名;(常用)
调用原型方法
构造方法.prototype.方法名();
实例化对象.方法名();
<script type="text/javascript">
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.country = "China";
Person.prototype.speak = function(){ console.log('hello world'); };
var p1 = new Person("张三",18);
console.log(p1.country);
console.log(p1.speak());
</script>
为什么对象可以获取原型中的内容?
每个对象中都有一个__proto__属性,这个属性指向了创建它时的那个原型对象,即构造方法.prototype === 对象.__proto__。对象之所以可以利用对象.属性的形式获取到原型中的内容是因为受到对象属性查找顺序影响,是顺序为:先在私有属性中查找该属性,如果有返回对应的值,如果没有这到它的原型中查找属性,如果有返回对应的值。注意如果私有属性名称和原型中的属性名称相同,那么私有属性会屏蔽掉原型中的属性
深入理解__proto__属性
js中万物都是对象,但是对象也分为:普通对象和函数对象,也就是Object 和 Function。
那么怎么区分普通对象和函数对象呢?凡是通过New Function()创建的对象都是函数对象,其他的都是普通对象。
需要注意的是:普通对象没有prototype(prototype即是属性也是对象),但是有__proto__属性。
js创建对象的时候都有一个__proto__内置属性,用于指向创建它的函数对象的原型对象prototype。
<script type="text/javascript">
function Person(name, age) {
this.name = name;
this.age = age;
}
var obj = {
country: "China",
speak: function() { console.log("hello world"); }
}
Person.prototype = obj;
console.log(Person.prototype.constructor); //constructor属性指向Object
Person.prototype.constructor = Person; //重新将constructor属性指向Person
console.log(Person.prototype.constructor);
</script>
将构造方法的prototype指向一个已经存在内容的对象。这种方式和手动逐条添加的方式有什么区别?
第一种方式会影响constructor属性的值。constructor属性是每个原型对象中的属性,该属性的作用是返回创建实例化对象的构造函数。建议在采用第二种方式更改原型时,将原型中的constructor属性重新指向构造函数
原型操作的常用方法
hasOwnProperty方法
功能:判断某个属性是否为该对象的私有属性
格式:对象名.hasOwnProperty("属性名");
返回值:true(是私有属性)、false(不是私有属性或者没有该属性)
in关键字
功能:判断某个属性是否为对象的属性
格式:"属性名" in 对象名;
返回值:true(该对象包含此属性)、false(该对象不包含此属性)
注意:in在判断时不仅会判断对象的私有属性,也会判断原型即原型链的属性
自定义方法,判断一个属性是否为原型中的属性
//当属性属于对象并且不是对象的私有属性时,判断属性属于原型属性
function 方法名(对象, 属性) {
if (属性 in 对象 && 对象.hasOwnProperty(属性) == false) {
return true;
} else {
return false;
}
}
function isPrototypeProperty(ele, proName) {
if (proName in ele && ele.hasOwnProperty(proName) == false) {
return true;
} else {
return false;
}
}
isPrototypeOf方法
作用:判断一个对象是否为另一个对象的原型对象
格式:对象1.isPrototypeOf(对象2);
返回值:true(对象1是对象2的原型对象)、false(对象1不是对象2的原型对象)
在IE浏览器中不识别__proto__属性
//定义一个函数,功能是解决在IE中__proto__属性不支持的问题
function getProto(ele, proName) {
if (ele.__proto__ != undefined) {
return ele[proName];
} else {
return ele.constructor.prototype[proName];
}
}
new关键字的作用
- 创建一个空对象,将该空对象赋值到this里面
- 将该空对象的__proto__属性指向原型对象
- 对该空对象进行属性的初始化工作
- 将此对象返回
动态原型模式
//原型是将所有实例共享的内容提取出来,如果没有创建实例时就创建原型,消耗空间,所以我们使用动态原型模式,在创建实例同时为原型赋值。
<script type="text/javascript">
function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
if (Person.prototype.country == undefined) { Person.prototype.country = "China"; }
if (Person.prototype.speak == undefined) { Person.prototype.speak = function() { console.log("hello"); }}
}
console.log(Person.prototype);
var p = new Person("Tom", 10, "男");
console.log(Person.prototype);
</script>