JavaScript原型与原型链深入探究使用方法

JavaScript原型与原型链深入探究使用方法

原型

JavaScript中每个函数都有一个prototype属性,它指向一个对象。这个对象就是所谓的“原型对象”或“原型”。我们可以在原型对象上添加方法和属性,这些方法和属性可以被构造函数创建的实例所共享。在原型对象上定义的方法和属性,可以被该构造函数所创建的所有实例共享使用。这样,我们就可以省略实例中相同的方法和属性了。

我们可以使用Object.getPrototypeOf()方法获取指定对象的原型对象,或者使用对象的__proto__属性获取其原型对象。

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.sayHello = function() {
  console.log("Hello, I'm " + this.name + " and I'm " + this.age + " years old.");
};

var p1 = new Person("Alice", 23);
var p2 = new Person("Bob", 24);

p1.sayHello(); // Hello, I'm Alice and I'm 23 years old.
p2.sayHello(); // Hello, I'm Bob and I'm 24 years old.

console.log(Object.getPrototypeOf(p1) === Person.prototype); // true
console.log(p1.__proto__ === Person.prototype); // true

原型链

JavaScript中除了Object对象没有原型,其他所有对象都有原型。当我们访问对象的一个属性时,JavaScript引擎会首先在该对象本身查找该属性,如果找到则直接返回该属性的值;如果没有找到,则继续在该对象的原型对象上查找该属性。如果仍然没有找到,则继续在原型对象的原型对象上查找,直到找到该属性或到达Object为止。

这种由多个对象构成的链式结构就是原型链。我们可以使用Object.create()方法来创建一个指定对象的新对象,并把新对象的原型对象指定为该指定对象,从而形成一个原型链。

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.sayHello = function() {
  console.log("Hello, I'm " + this.name + " and I'm " + this.age + " years old.");
};

function Student(name, age, grade) {
  Person.call(this, name, age);
  this.grade = grade;
}

Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.sayGrade = function() {
  console.log(this.name + "'s grade is " + this.grade + ".");
};

var s1 = new Student("Alice", 23, "A");
var s2 = new Student("Bob", 24, "B");

s1.sayHello(); // Hello, I'm Alice and I'm 23 years old.
s1.sayGrade(); // Alice's grade is A.
s2.sayHello(); // Hello, I'm Bob and I'm 24 years old.
s2.sayGrade(); // Bob's grade is B.

console.log(Object.getPrototypeOf(s1) === Student.prototype); // true
console.log(Object.getPrototypeOf(Student.prototype) === Person.prototype); // true
console.log(Object.getPrototypeOf(Person.prototype) === Object.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype) === null); // true

在上面的示例中,使用Object.create()方法创建了一个新对象,并把原型对象指定为Person.prototype,从而形成了一个原型链。由于我们重写了Student.prototype对象,导致其原型对象不再指向Object.prototype,所以要手动给Student.prototype重新设置constructor属性。在该原型链中,Student的实例Student.prototype的原型对象是Person.prototypePerson的实例的原型对象是Object.prototype,最高层原型对象是null。为了提高代码的可读性,我们可以使用ES5中新增的Object.setPrototypeOf()方法来设置对象的原型对象。

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.sayHello = function() {
  console.log("Hello, I'm " + this.name + " and I'm " + this.age + " years old.");
};

function Student(name, age, grade) {
  Person.call(this, name, age);
  this.grade = grade;
}

Object.setPrototypeOf(Student.prototype, Person.prototype);
Student.prototype.sayGrade = function() {
  console.log(this.name + "'s grade is " + this.grade + ".");
};

var s1 = new Student("Alice", 23, "A");
var s2 = new Student("Bob", 24, "B");

s1.sayHello(); // Hello, I'm Alice and I'm 23 years old.
s1.sayGrade(); // Alice's grade is A.
s2.sayHello(); // Hello, I'm Bob and I'm 24 years old.
s2.sayGrade(); // Bob's grade is B.

console.log(Object.getPrototypeOf(s1) === Student.prototype); // true
console.log(Object.getPrototypeOf(Student.prototype) === Person.prototype); // true
console.log(Object.getPrototypeOf(Person.prototype) === Object.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype) === null); // true

示例说明

示例一

在以下示例中,我们定义了一个Animal的构造函数,该构造函数拥有一个eat方法的原型。我们接着从Animal继承一个Dog构造函数,并通过原型链给Dog添加一个bark方法。最后,使用Dog构造函数创建了一个d对象。我们可以发现,d可以调用eatbark两个方法。

function Animal(name) {
    this.name = name;
}

Animal.prototype.eat = function() {
    console.log(this.name + " is eating.");
};

function Dog(name) {
    this.name = name;
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.bark = function() {
    console.log(this.name + " is barking.");
};

var d = new Dog("Gunner");
d.eat();
d.bark();

示例二

在以下示例中,我们定义了一个Shape的构造函数,该构造函数拥有一个getType方法的原型。我们接着从Shape继承一个Rectangle构造函数,并重写了该构造函数的getType方法来返回特定的type属性。最后,使用Rectangle构造函数创建了一个r对象。我们可以发现,rgetType方法返回了rectangle

function Shape() { }

Shape.prototype.getType = function() {
    return "shape";
}

function Rectangle() { }

Rectangle.prototype = Object.create(Shape.prototype);

Rectangle.prototype.constructor = Rectangle;

Rectangle.prototype.getType = function() {
    return "rectangle";
}

var r = new Rectangle();
console.log(r.getType());

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript原型与原型链深入探究使用方法 - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • C#监测IPv4v6网速及流量的实例代码

    先给出完整的攻略目录,方便理清思路: 前置知识:C#网络库的使用 监测IPv4v6网速及流量的实现方法 示例1:监测本机流量并将数据保存至文件 示例2:通过Ping测试监测网络延迟 下面我就从这个目录入手,逐一给出详细的说明: 前置知识:C#网络库的使用 在监测网速和流量时,我们需要使用C#的网络库来进行网络通信相关操作。C#网络库主要包括Socket、We…

    JavaScript 2023年5月28日
    00
  • el-form-item prop属性动态绑定不生效问题及解决

    下面是“el-form-item prop属性动态绑定不生效问题及解决”的完整攻略: 问题描述 在Vue.js的Element UI框架中,使用el-form-item组件时,有时即便将组件的prop属性动态绑定到数据对象上,但修改数据对象时却没有触发组件的重新渲染,导致绑定失效。 例如,如下代码中的el-form-item组件,虽然将其prop属性disa…

    JavaScript 2023年6月10日
    00
  • 纯javascript判断查询日期是否为有效日期

    针对“纯javascript判断查询日期是否为有效日期”的问题,我给出如下攻略: 1.判断规则 要判断日期是否有效,需要先确定日期的格式。在常见的日期格式中,比较常用的是以下三种: 年月日格式:如2022-07-01; 月日年格式:如07/01/2022; 日月年格式:如01.07.2022。 无论哪种日期格式,都需要满足一些规则才能算是有效的日期。下面列出…

    JavaScript 2023年5月27日
    00
  • JavaScript对象学习小结

    下面是关于“JavaScript对象学习小结”完整攻略的详细讲解。 一、对象 JavaScript 中的对象是一组属性的集合,其中每个属性通过键与值相关联。可以通过多种方式创建对象。 1.1 对象的创建 可以使用对象字面量创建对象,对象字面量是一个逗号分隔的键值对的列表,放在花括号中。 例如: var student = { name: ‘Tom’, age…

    JavaScript 2023年5月27日
    00
  • jQuery form插件之formDdata参数校验表单及验证后提交

    下面是详细讲解“jQuery form插件之formData参数校验表单及验证后提交”的完整攻略。 什么是jQuery form插件? jQuery form插件是一个可以方便处理表单提交的jQuery插件,它简化了表单提交时的Ajax处理,并提供了一些表单处理辅助功能。 什么是formData参数 formDataparams刷新时将用于测试表单中所有可用…

    JavaScript 2023年6月10日
    00
  • JavaScript的Vue.js库入门学习教程

    JavaScript的Vue.js库入门学习教程 什么是Vue.js? Vue.js是一款流行的JavaScript库,用于构建用户界面。它是一个MVVM模式的库,即Model-View-ViewModel的缩写,由Evan You在2014年开始编写,并在GitHub上发布。Vue.js具有小巧、快速、易于学习和灵活的特点,能够简化Web应用程序的开发过程…

    JavaScript 2023年5月27日
    00
  • Bootstrap源码解读表单(2)

    关于“Bootstrap源码解读表单(2)”这篇文章,主要是对Bootstrap框架中的表单组件的源码分析和实现方法进行了详细讲解。下面是我对这篇文章的完整攻略: 简介 此文章是 Bootstrap 源码解读系列的第 2 篇,主要介绍如何自定义表单组件,以及其中用到的几个重要的 CSS 类。 自定义表单组件 Bootstrap 的表单组件样式是十分灵活的,可…

    JavaScript 2023年6月10日
    00
  • webpack将js打包后的map文件详解

    一、简介 当我们使用webpack将JavaScript代码打包合并成单个文件时,webpack会自动生成一个source map文件。这个文件的作用是将打包后的文件中的代码映射回未打包前的原始代码,方便我们调试和定位错误。本文将详细讲解webpack生成的source map文件的格式和使用方法。 二、source map文件格式 Webpack生成的so…

    JavaScript 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部