原型与原型链

原型 & 原型链

  • 所有对象都是通过new 函数创建
  • 所有的函数也是对象
    • 函数可以有属性和方法
  • 所有对象都是引用类型

原型 prototype

原型: 任何一个JS对象创建时会关联的一个对象 任何根据原型的构造函数创建出来的对象,都会继承原型上的属性

  • 所有函数都有一个prototype属性
  • 默认情况下,prototype属性是一个普通的Object对象
  • 默认情况下,prototype对象有一个属性constructor,它也是一个对象,指向构造函数本身

隐式原型__proto__

  • 所有的对象都有一个__proto__属性,称为隐式原型
  • 默认情况下,隐式原型指向创建该对象的函数的原型
javascript 复制代码
function test() {}
var obj = new test();
obj.__proto__ === test.prototype // true
javascript 复制代码
function create() {
    if (Math.random() < 0.5) {
        return {}
    } else {
        return []
    }
}
var obj = create();
// 得到创建obj的构造函数名称
console.log(obj.__proto__.constructor.name)

当访问一个对象的成员时:

  1. 看该对象自身是否有该成员,如果有直接使用
  2. 在原型链中依次查找是否有该成员,如果有直接使用

原型链

原型链: 原型链是一个对象到另一个对象的链接,它是由__proto__属性连接起来的一系列对象,直到到达null(即对象查找属性的过程) 特殊点:

  1. Function的__proto__指向自身的prototype
  2. Object的prototype__proto__指向null

图解原型链

面试题

javascript 复制代码
// 面试题一
var F = function() {};
Object.prototype.a = function () {}
Function.prototype.b = function () {}
var f = new F();

console.log(f.a, f.b, F,a, F.b)
// function () {} undefined function() {} function() {}
javascript 复制代码
// 面试题二
function A() {}
function B(a) {
    this.a = a;
}
function C(a) {
    if (a) {
        this.a = a;
    }
}
A.prototype.a = 1;
B.prototype.a = 1;
C.prototype.a = 1;

console.log(new A().a) // 1
console.log(new B().a) // undefined
console.log(new C(2).a) // 2
javascript 复制代码
// 面试题三
function User() {}
User.prototype.sayHello = function() {}

var u1 = new User();
var u2 = new User();

console.log(u1.sayHello === u2.sayHello); //true
console.log(User.prototype.constructor); //User Function
console.log(User.prototype === Function.prototype); // false
console.log(User.__proto__ === Function.prototype); // true
console.log(User.__proto__ === Function.__proto__); // true
console.log(u1.__proto__ === u2.__proto__);  // true
console.log(u1.__proto__ === User.__proto__); // false
console.log(Function.__proto__ === Object.__proto__); // true
console.log(Function.prototype.__proto__ === Object.prototype.__proto__); // false
console.log(Function.prototype.__proto__ === Object.prototype); // true

原型链的应用

基础方法

Object.getPrototypeOf(对象) 获取对象的原型 Object.prototype.isPrototypeOf(对象) 判断当前对象(this)是否在指定对象的原型链上 对象 instanceof 函数 判断函数的原型是否在对象的原型链上 Object.create(原型对象,属性对象) 创建一个对象,其隐式原型指向指定的对象 Object.prototype.hasOwnProperty(属性名) 判断一个对象自身是否拥有某个属性

应用

类数组转换为真数组

javascript 复制代码
Array.prototype.slice.call(arguments); // arguments为类数组

实现继承 默认情况下,所有构造函数的父类都是Object

javascript 复制代码
// 实现继承
function inhreit(Son, Father) {
  // 第一种方案
  // Son.prototype = Father.prototype; // 容易造成原型链污染
  // 第二种方案
  // Son.prototype = Object.create(Father.prototype); // 创建一个对象,其隐式原型指向父类的原型对象prototype
  // 第三种方案
  var F = function () {
  };
  F.prototype = Father.prototype;
  Son.prototype = new F();
  Son.prototype.constructor = Son; // 修正构造函数指向
  // Son.prototype.uper = Father; // 增加父类引用
  Son.prototype.uper = Father.prototype; // 增加父类原型对象引用
}

function User(firstName, lastName, age) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.age = age;
  this.fullName = firstName + " " + lastName;
}

User.prototype.sayHello = function () {
  console.log(`大家好,我是${this.fullName},今年${this.age}岁了!`)
}

function VipUser(firstName, lastName, age, money) {
  User.call(this, firstName, lastName, age)
  this.money = money;
}

inhreit(VipUser, User)
VipUser.prototype.upgrade = function () {
  console.log(`使用${this.money}元,升级VIP会员!`)
}
const vUser = new VipUser('Tom', 'Hanks', 25, 10000)
相关推荐
AndyGoWei5 分钟前
写一个带联想词的输入框,看这篇文章就够了
前端·javascript
阿信无月10 分钟前
数组排序
javascript
申朝先生28 分钟前
JS:什么是闭包,以及它的应用场景和缺点是什么?
开发语言·javascript·ecmascript
念九_ysl31 分钟前
暴力搜索算法详解与TypeScript实战
javascript·算法
uhakadotcom1 小时前
Meta Horizon OS 开发工具:打造更好的 MR/VR 体验
javascript·后端·面试
helbyYoung2 小时前
【零基础JavaScript入门 | Day7】三大交互案例深度解析|从DOM操作到组件化开发
开发语言·javascript
uhakadotcom2 小时前
刚刚发布的React 19.1提供了什么新能力?
前端·javascript·面试
uhakadotcom2 小时前
Expo 简介:跨平台移动应用开发的强大工具
前端·javascript·面试
red润3 小时前
npm包autocannon牛逼的后台压力测试库
前端·javascript·node.js
渔樵江渚上3 小时前
JavaScript函数柯里化:优雅的函数式编程实践
前端·javascript·面试