原型
概述
原型是什么
在JavaScript中,函数是一个包含属性和方法的Function类型的对象原型(Prototype)是Function类型对象的一个属性。
在函数定义时就包含了Prototype属性,它的初始值是一个空对象。在JavaScript中并没有定义函数的原型类型,所以原型是任何类型的。
原型用于保存对象的共享属性和方法,原型的属性和方法并不会影响函数本身的属性和方法。
获取原型
//通过构造函数的Prototype属性获取原型
function fun() {
console.log('this is function');
};
console.log(fun.prototype);//fun{}
console.log(fun['prototype']);//fun{}
//通过Object对象的getPortotypeOf(函数名)方法
console.log(Object.getPrototypeOf(fun));//[Function]
原型的属性和方法
function fun() {
console.log('this is function')
}
/* 设置属性的原型和方法
函数名.prototype.属性名 = 属性值
函数名.prototype.方法名 = function(){}*/
fun.prototype.name = '花间集';
console.log(fun.prototype.name)//花间集
原型属性
自有属性和原型属性
- 自有属性:通过对象的引用添加的属性。其他对象无此属性,即使有,也是不彼此立的属性
- 原型属性:从原型对象中继承来的属性,一旦原型对象属性值改变,所有继承该原型的对象属性都改变
//定义构造函数
function fun(agg) {
//构造函数本身的属性或方法-自有属性
this.agg = agg;
this.age = function () {
console.log(100)
}
}
//通过原型新增的属性或方法-原型属性
fun.prototype.name = '白';
/* 通过构造函数创建对象
* *不仅有构造函数的自有属性
* *好友构造函数的原型属性*/
var fn = new fun(1);
console.log(fn.name);//白
console.log(fn.agg);//1
检测原型属性
function fun() {
this.name = '花间集'//自有属性
}
//原型属性
fun.prototype.name = '温庭筠';
//通过构造函数创建对象
var fn = new fun();
/* Object.hasOwnPrototy(属性名称)方法
* 返回值-布尔值
* true-表示存在指定的自有属性
* false-表示不存在指定的自有属性*/
console.log(fun.hasOwnProperty('name'))//true
/* 使用in关键字检测对象的属性
* 判断对象中是否存在是定属性(自有属性或原型属性)
* 返回值-布尔值*/
console.log('name' in fun);//true
重写与删除原型属性
//创建构造函数
function fun() {
this.name = '村上春树'
}
//新增与自有属性同名的原型属性
fun.prototype.name = '西尾维新';
//用构造函数创建对象
var fn = new fun();
//当自有属性和原型属性同名时,自有属性的级别高于原型属性
console.log(fn.name);//村上春树
//删除对象的属性,自有属性和原型属性同名,先删除自有属性。
//再删除一次则删除原型属性
delete fn.name;
//重新访问对象的属性
console.log(fn.name);//西尾维新
isPrototypeOf()方法
该方法用来判断对象是否是另一个对象的原型
//通过初始化器方式定义对象
var obj ={
name : '花间集'
};
//定义构造函数
function Fun () {
this.agg = 2
}
//将对象obj赋值于函数Fun的原型
Fun.prototype=obj;
//用构造函数创建对象
var fn = new Fun();
//判断对象obj是不是对象fn的原型
var f = obj.isPrototypeOf(fn);
console.log(f);//true
扩展内建对象
JavaScript中的内置对象有些也具有Prototype属性,利用内置对象的prototype属性可以为内置对象扩展属性或者方法。
一般建议慎用这种方式,可能会应浏览器版本问题导致冲突。
继承
原型链
/* 原型链
* 类似于子级可以直接使用父级的属性或者方法
* 构造函数或者对象的原型一级一级的指向Object的原型
* 后面的可以直接使用前面的原型定义->实现继承*/
function A () {
this.a = 'a'
}
var a = new A();//通过构造函数创建对象
function B () {
this.b = 'b'
}
//B函数的原型指向对象a
B.prototype=a;
//构造函数创建对象
var b = new B();
console.log(b.a);//a
console.log(b.b);//b
function C () {
this.c = 'c'
}
//C函数的原型指向b对象
C.prototype=b;
//创建构造函数
var c = new C();
console.log(c.a);//a
console.log(c.b);//b
console.log(c.c);//c
只继承于原型的原型链
出于对效率的考虑,尽可能的降属性和方法添加到原型上。
- 不要为继承关系单独创建新对象
- 尽量减少运行时的方法搜索
function A () {
//将自身属性改为原型属性
}
A.prototype.a='a';
function B () {
}
B.prototype = A.prototype;
B.prototype.b='b';
var b = new B();
console.log(b.a);//a
console.log(b.b);//b
function C () {
this.c='c'
}
C.prototype = B.prototype;
var c = new C();
console.log(c.a);//a
console.log(c.b);//b
console.log(c.c);//c
原型链的问题
- 原型链实际上是多个构造函数或者对象之间共享属性和方法
- 创建子级的对象时,不能像父级的构造函数传递任何参数
实际开发中,很少单独使用原型链。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。