原型

概述

原型是什么

在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

原型链的问题

  • 原型链实际上是多个构造函数或者对象之间共享属性和方法
  • 创建子级的对象时,不能像父级的构造函数传递任何参数

实际开发中,很少单独使用原型链。


李威振
16 声望5 粉丝

别离时方知此世间,花亦花来人亦人