函数对象中的原型属性
- 每个函数中都有一个prototype属性,该属性所存储的就是原型对象
- 为原型对象添加属性
- 使用原型对象中的新增属性
- 区分对象自身属性和原型属性
- —proto— 用于保存各对象原型的链接
- 介绍原型方法
原型属性
函数对象的属性 prototype 原型属性,在函数定义时被创建。初始值是一个空对象
function f(){
console.log(2)
}
f.length
f.constructor
typeof f.prototype
利用原型添加方法和属性
通过构造器函数,来构造对象,这种做法的主要目的是通过new操作符来调用函数,以达到访问对象this值得目的,然后构造器就可以将其所创建的对象返回给我们。这样,我就有了一种赋予新建对象一定功能(即为其添加属性和方法)的方法。
function Cat(name,color){
this.name = name; // name 和 color 以及 sayName方法 都是在新建时添加的。
this.color = color;
this.sayName = function(){
return `我的名字是${this.name},我是一只${this.color}颜色的猫!`
}
}
// 添加属性和方法还有另一种方式,即通过构造器函数的prototype属性来新增。
// 由于prototype 属性包含的是一个对象,该对象构造函数就是 Cat
Cat.prototype = {
pricie:100,
run: function(){
return '跑起来'
}
}

使用原型的方法和属性
上面向Cat的原型添加完方法和属性后,就可以直接用Cat构造器来新建对象了.
对原型来说,要理解它的驻留概念。
因为在js中,对象都是通过引用的方式来传递的,因此我们所创建的每个新对象实体中并没有一份属于自己的原型副本。
这样的话,我们可以随时修改原型,并且与之相关的对象也是都会继承这些改变。
var bigCat = new Cat('小青龙','白');
bigCat.name // "小青龙"
bigCat.sayName() // "我的名字是小青龙,我是一只白颜色的猫!"
bigCat.pricie // 100
bigCat.run() // "跑起来"
// 对象都是通过引用的方式来传递的,因此我们所创建的每个新对象实体中并没有一份属于自己的原型副本。
Cat.prototype.get = function(what){
return this[what];
}
bigCat.get('color') // "白"
自身属性和原型属性
sayName 我们是通过this指针来完成对象的访问,其实也可以直接引用
Cat.prototype.sayName
function Cat(name,color){
Cat.prototype.name = name; // name 和 color 以及 sayName方法 都是在新建时添加的。
Cat.prototype.color = color;
Cat.prototype.sayName = function(){
return `我的名字是${this.name},我是一只${this.color}颜色的猫!`
}
}


x.constructor.prototype.constructor 这种结构可能会一直下去,最终取决于原型链的长度,但最后一环肯定是Obejct内建对象。因为它是最高级的父级对象。
结论:
如果一个对象自身属性中没有找到指定的属性,就可以去原型链中查找相关的属性
疑问?
如果遇上对象的自身属性和原型属性同名是怎么样的?
对象自身属性的优先级高于原型属性。
利用自身属性重新原型属性
为什么能重写?因为对象自身属性的优先级高于原型属性。
function Pig(name){
this.name = name;
}
Pig.prototype.name = '渣渣';
var too = new Pig('ben'); // 新建too对象,并访问name属性
too.name // "ben"
delete too.name // true // 删除name属性
too.name // "渣渣" 访问原型上的同名属性
too.name = "xin";
too.name // "xin"

对象的枚举属性
想获取一个对象的所有属性列表,可以使用for-in循环
需注意:
- 不是所有的属性都会出现在for-in循环中,比如(数组的)length属性和constructor属性就不会显示。那些已经被显示的数据被称为是可枚举的;可以通过对象提供的protertyIsEnumerable()方法来判断其中有哪些可枚举的属性。
- 原型链中的各个原型属性也会被显示出来。前提是可枚举的。我们可以通过对象的 可以通过hasOwnProperty()方法来判断一个属性是对象自身属性还是原型属性。
- 对于是有的原型属性,protertyIsEnumerable()都会返回false,包括在for-in循环中可以枚举的属性。
isPrototypeOf()方法
每个对象中都会有一个isPrototypeOf()方法,用来判断当前对象是否是另一个对象的原型。

var cat = {
color:'bai'
}
function Animal(name){
this.name = name;
}
Animal.prototype = cat;
var bigCat = new Animal('bigCat');
cat.isPrototypeOf(bigCat) // true
总结
- 所有函数都会有一个叫做prototype的属性,默认初始值为一个空对象。
- 可以在相关的原型对象中添加新的方法和属性,甚至可以用自定义对象来完全替换掉原有的原型对象。
- 通过某个构造器函数新建对象时(new 操作符),这些对象就会自动拥有一个指向各自prototype属性的链接--proto--,并且可以通过它访问相关原型对象的属性。
- 对象自身属性的优先级要高于其原型对象中的同名属性;
- 可以通过hasOwnProperty()方法来区分对象的自身属性和原型属性;
- 原型链的存在:一个对象中访问一个并不存在的属性时,js引擎会搜索该对象的原型上的同名属性。如果依然没找到,则会继续搜索其原型的原型,以此类推,直到最高级的父级对象Object.
- 可以对内建的构造器函数进行扩展,以便所有的对象都能引用新增的功能。再添加相关的方法和属性之前,应该做一些已有方法的检测工作。增加脚本对于未来环境的适应能力。