JS面向对象中的原型

原型

原型是什么

在JavaScript中,函数是一个包含属性和方法的Function类型的对象。而原型(Prototype)就是Function类型对象的一个属性。

在函数定义时就包含了prototype属性,它的初始值是一个空对象。在JavaScript中并没有定义函数的原型类型,所以原型可以是任何类型。

原型是用于保存对象的共享属性和方法的,原型的属性和方法并不会影响函数本身的属性和方法。

//Function类型的属性 -> 所有函数都具有的属性
console.log(Function.prototype);//[Function]

//定义函数
function fn() {
    console.log('this is a function');
}
//原型的默认值是空对象
console.log(fn.prototype);//fn {}

//函数包含构造函数 -> 所有引用类型其实都是构造函数
console.log(Number.prototype);//[Number: 0]

console.log(Object.prototype);//{}

//为什么Object.prototype出来的是{},可以使用学过的东西进行验证,
//随机获取一个Object的属性的属性描述符
var result = Object.getOwnPropertyDescriptor(Object.prototype,'constructor');
console.log(result);//因为enumerable: false,不可遍历

效果:
在这里插入图片描述

获取原型

通过如下两种方式可以获取对象的原型,从而设置共享的属性和方法:

  • 通过构造函数的prototype属性。

    function Person(){
    	console.log('Person instantiated');
    }
    console.log(Person.prototype);
    
  • 通过Object对象的getPrototype(obj)方法。

    function Person(){
    	console.log('Person instantiated');
    }
    console.log(Object.getPrototypeOf(Person));
    

    代码:

    function fn() {
        console.log('this is a function');
    }
    //使用访问对象的属性语法结构
    console.log(fn.prototype);//fn {}
    console.log(fn['prototype']);//fn {}
    //Object类型提供getPrototypeOf()方法
    console.log(Object.getPrototypeOf(fn));//[Function]  这是运行环境的问题,在浏览器就不一样
    

    效果:
    在这里插入图片描述

在这里插入图片描述

原型的属性和方法

通过如下两种方式可以设置原型的属性和方法:

  • 原型的属性和方法单独进行定义。

    构造函数.prototype.属性名 = 属性值;
    构造函数.prototype.方法名 = function(){}
    
  • 直接为原型定义一个新对象

    构造函数.prototype = {
    	属性名 : 属性值,
    	方法名 : function(){}
    }
    

代码:

function fn() {
    console.log('this is a function');
}
//变量proto也是一个空对象
// var proto = fn.prototype;
// 新增属性或方法
// proto.name = '肖德硕';
fn.prototype.name = '肖德硕';
console.log(fn.prototype);
// defineProperty()
Object.defineProperty(fn.prototype,'age',{
    value : 18,
    enumerable : true
});
console.log(fn.prototype);

效果:
在这里插入图片描述

构造函数的原型

//定义构造函数
function Hero(){
    this.name = '肖德硕';
    this.sayMe= function () {
        console.log('this is a function');
    }
}
//操作构造函数Hero的原型
Hero.prototype.age = 18;

//利用构造函数Hero来创建对象
var hero = new Hero();
console.log(hero);//Hero { name: '肖德硕', sayMe: [Function] }
//为构造函数的原型新增的属性 -> 构造函数创建对象中依旧可以访问
console.log(hero.age);//18
//对象hero中不存在age属性
var result = Object.getOwnPropertyDescriptor(hero,'age');
console.log(result);//undefined

效果:
在这里插入图片描述

在这里插入图片描述

自有属性与原型属性

  • 自有属性:通过对象的引用添加的属性。其他对象可能无此属性;即使有,也是彼此独立的属性
  • 原型属性:从原型对象中继承来的属性,一旦原型属性对象中属性值改变,所有继承自该原型的对象属性均改变。
//定义构造函数
function Hero(name){
    //构造函数本身的属性 -> 自有属性
    this.name = name;
    this.sayMe= function () {
        console.log('this is a function');
    }
}
//通过构造函数Hero的prototype新增属性或方法
//通过原型所定义的属性 -> 原型属性
Hero.prototype.age = 18;

/*
    通过构造函数Hero创建对象时
      不仅具有构造函数的自有属性
      还具有构造函数的原型属性
* */

var hero = new Hero('肖德硕');
console.log(hero.name);
console.log(hero.age);

var hero2 = new Hero('小肖');
console.log(hero2.name);
console.log(hero2.age);

//为对象hero新增age属性
// hero.age = 80;
// console.log(hero.age);//80
//
// console.log(hero);//Hero { name: '肖德硕', sayMe: [Function], age: 80 }
//
// console.log(hero2.age);//18

Hero.prototype.age = 80;
console.log(hero.age);
console.log(hero2.age);

效果:
在这里插入图片描述

自有属性与原型属性的优先级

自有属性与原型属性同名时,默认访问的是自有属性 -> 自有属性的优先级高于原型属性

代码:

//定义构造函数
function Hero(){
    this.name = '肖德硕'
}

//构造函数的原型
Hero.prototype.name = '小肖';
//构造函数创建对象
var hero = new Hero();
//自有属性与原型属性同名时,默认访问的是自有属性 -> 自有属性的优先级高于原型属性
console.log(hero.name);//肖德硕

//删除对象的属性
delete hero.name;
console.log(hero.name);//小肖

效果
在这里插入图片描述

检测自有或原型属性

  • 使用hasOwnProperty()方法检测对象是否具有指定的自有属性

    function Hero(){}
    var hero = new Hero();
    console.log(hero.hasOwnPrototype("name"));
    
  • 使用in关键字检测对象及其原型链中是否具有指定属性:

    function Hero(){}
    var hero = new Hero();
    console.log("name" in hero);
    

代码:

function Hero() {
    this.name = '肖德硕'
}
Hero.prototype.name = '小肖';

var hero = new Hero();
/*
      Object.hasOwnProperty(prop)方法
        作用 - 判断当前指定属性是否为自有属性
        参数
          prop - 表示指定属性名称
        返回值 - 布尔值
          true - 表示存在指定的自有属性
          false - 表示不存在指定的自有属性
* */
console.log(Object.hasOwnProperty('name'));//true

/*
    使用in关键字检测对象的属性
     作用 - 判断对象中是否存在指定属性(自有属性或原型属性)
     返回值 - 布尔值
       true - 表示存在指定的属性
       false - 表示不存在指定的属性
* */
console.log('name' in hero);//true

操作原型的方式

1.利用对象.属性或方法的方式新增属性或方法

Hero.prototype.name = '肖德硕';
Hero.prototype.sayMe = function(){
    console.log('this is function');
}

2.将原型重新赋值为一个新对象

Hero.prototype = {
    name : '肖德硕',
    sayMe : function(){
        console.log('this is function');
    }
}

代码:

// 定义构造函数
function Hero(){}
// 通过构造函数的原型新增属性或方法

// 1.利用对象.属性或方法的方式新增属性或方法
Hero.prototype.name = '肖德硕';
Hero.prototype.sayMe = function(){
    console.log('this is function');
}
// 2.将原型重新赋值为一个新对象
Hero.prototype = {
    name : '肖德硕',
    sayMe : function(){
        console.log('this is function');
    }
}

// 通过构造函数创建对象
var hero = new Hero();

console.log(hero.name);
hero.sayMe();

效果:
在这里插入图片描述

在这里插入图片描述

显式原型与隐式原型

所有对象其实也具有原型
注意 - 对象的原型(__proto__)并非是函数的原型(prototype)
区分
将函数的原型 -> 显式原型
将对象的原型 -> 隐式原型
对象的原型
不能用于真实开发工作,仅用于逻辑测试

// 定义构造函数
function Hero(){
    this.name = '肖德硕';
}
// 通过构造函数的原型新增属性或方法
Hero.prototype.age = 18;
// 通过构造函数创建对象
var hero = new Hero();

console.log(hero.name);// 对象调用自有属性
console.log(hero.age);// 对象调用原型属性

/*
    所有对象其实也具有原型
     注意 - 对象的原型(__proto__)并非是函数的原型(prototype)
     区分
       将函数的原型 -> 显式原型
       将对象的原型 -> 隐式原型
     对象的原型
       不能用于真实开发工作,仅用于逻辑测试
 */
console.log(hero.prototype);// undefined 表示对象中不存在该属性
console.log(hero.__proto__);

效果:
在这里插入图片描述

isPrototypeOf()方法

每个对象中都会具有一个isPrototypeOf()方法,该方法用来判断一个对象是否是另一个对象的原型

代码:

// 通过初始化器方式定义对象
var obj = {
    name : '肖德硕'
}
// 定义构造函数
function Hero(){}
// 将对象obj赋值给构造函数Hero的原型
Hero.prototype = obj;
// 通过构造函数创建对象
var hero = new Hero();
// 判断指定对象是否是另一个对象的原型
var result = obj.isPrototypeOf(hero);

console.log(result);

效果:
在这里插入图片描述

扩展內建对象

JavaScript中的内置对象有些也具有prototype属性,利用内置对象的prototype属性可以为内置对象扩展属性或方法

通过原型扩展内置对象的属性和方法非常灵活,根据个性化要求制定JavaScript语言的具体内容。

一般建议慎用这种方式,如果JavaScript的版本更新时可能会提供个性化的属性或方法,导致冲突。

代码:

Object.prototype.sayMe = function(){
    console.log('this is sayMe function');
}
// 通过Object构造函数创建对象
var obj = new Object();

obj.sayMe();


Array.prototype.inArray = function(color){
    // this - 表示当前的数组
    for(var i = 0, len = this.length; i < len; i++){
        if(this[i] === color){
            return true;
        }
    }
    return false;
}
var arr = ["red", "green", "blue"];

console.log(arr.inArray("red")); //true
console.log(arr.inArray("yellow")); //false

效果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值