从0开始完全掌握JS中的原型

前言

许多刚入门前端的朋友可能会难以理解js中的原型和原型链,对这个概念非常模糊,然而,理解原型链是成为JavaScript高手的必备技能之一 。下面,我将详细讲解这些概念,希望能帮助你更好地掌握它们。

在讲原型之前,我们先了解下js的对象

对象

对象是数据结构的一种基本形式,用于存储各种类型的数据。对象可以被视为一组无序的键值对(key-value pairs),其中键(key)通常是字符串或符号(Symbol),值(value)可以是任何数据类型,包括数字、字符串、布尔值、数组、函数或其他对象。

  • 创建对象的方式

    • 对象字面量

      这是最简单且常见的创建对象的方式,只需要用一个{}来包含键值对就行,它可以在创建对象后随时添加、修改或删除属性和方法。但只适合创建单个对象,不适合批量创建多个具有相同属性和方法的对象。

    js 复制代码
    let mei = {
      name:'小美',
      age:18,
      hometown:'北京',
      sayHi(){
        console.log(`我叫${this.name},来自${this.hometown}`)
      }
    }
    mei.sayHi() // 我叫小美,来自北京
    • class类

      ES6 引入了class关键字,使得面向对象编程更加简洁直观,比较类似于传统面向对象语言(如Java或C#)中的类。

    js 复制代码
    class Person {
    constructor(name, age) {
      this.name = name;
      this.age = age;
      console.log(this.name + this.age);
      
    }
    
    greet() {
      console.log('你好,我是' + this.name);
    }
    }
    
    let person1 = new Person('张三', 28); //张三28
    let person2 = new Person('李四', 30); //李四30
    person1.greet(); // 你好,我是张三
    • 构造函数
    1. 构造函数通常用于实现面向对象编程中的类(尽管js并没有真正的类,直到ES6才引入了class关键字)。构造函数通过new运算符调用,通常是首字母大写用以区分普通函数,但这并不是强制性的,只是大家约定俗成的一种规矩
    js 复制代码
    function Person(name,age){
      console.log(this); // 会打印global
      this.name = name
      this.age = age
    }
    Person('小明',18) // 普通函数调用
    let xiaoming = new Person('小明',18) // 构造函数调用
    1. 构造函数,可以创建多个具有相同属性和方法的对象实例,由this指针指向实例对象。
    js 复制代码
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    let person1 = new Person('张三', 28);
    let person2 = new Person('李四', 30);
    // 检查 this 指向
    console.log(person1.name); // 输出: 张三
    console.log(person2.name); // 输出: 李四

原型和原型链

原型

JavaScript对象都有一个内部属性 [[Prototype]],它指向该对象的原型对象。 __proto__ 是一个访问器属性,允许你在对象上读取或设置 [[Prototype]]属性,通过构造函数创建的对象拥有构造函数内部定义的属性和方法

scss 复制代码
```js
function Person(name, age) {
    this.name = name;
    this.age = age;
}

// 为原型对象添加一个方法
Person.prototype.greet = function() {
    console.log('你好,我是' + this.name);
};

let person1 = new Person('张三', 28);

// 访问 person1 的原型对象
console.log(person1.__proto__); // 输出: Person { greet: [Function: greet] }

// 检查 person1 的原型对象是否等于 Person.prototype
console.log(person1.__proto__ === Person.prototype); // 输出: true

// 调用实例上的方法
person1.greet(); // 输出: 你好,我是张三

// 动态添加一个新方法到原型对象
Person.prototype.sayHello = function() {
    console.log('你好,世界!');
};

// 调用新添加的方法
person1.sayHello(); // 输出: 你好,世界!

// 创建另一个 Person 实例
let person2 = new Person('李四', 30);

// 调用新添加的方法
person2.sayHello(); // 输出: 你好,世界!

// 修改 person1 的原型对象
person1.__proto__ = {
    greet: function() {
        console.log('你好,我是新的' + this.name);
    },
    sayBye: function() {
        console.log('再见!');
    }
};

// 再次调用 person1 上的方法
person1.greet(); // 输出: 你好,我是新的张三
person1.sayBye(); // 输出: 再见!
```

原型链

试访问一个对象的某个属性或方法时,如果该对象自身没有这个属性或方法,JavaScript引擎会沿着原型链向上查找,直到找到该属性或方法为止,或者到达原型链的末端(即 null)。

ini 复制代码
```js
let baseObject = {
    baseMethod: function() {
        console.log('这是基础方法');
    }
};

// 定义一个中间对象,继承自 baseObject
let middleObject = Object.create(baseObject);
middleObject.middleMethod = function() {
    console.log('这是中间方法');
};

// 定义一个最终对象,继承自 middleObject
let finalObject = Object.create(middleObject);
finalObject.finalMethod = function() {
    console.log('这是最终方法');
};

// 尝试访问 finalObject 的属性和方法
finalObject.finalMethod(); // 输出: 这是最终方法
finalObject.middleMethod(); // 输出: 这是中间方法
finalObject.baseMethod(); // 输出: 这是基础方法

// 尝试访问一个不存在的属性
console.log(finalObject.someProperty); // 输出: undefined

// 检查原型链
console.log(finalObject.__proto__ === middleObject); // 输出: true
console.log(middleObject.__proto__ === baseObject); // 输出: true
console.log(baseObject.__proto__ === Object.prototype); // 输出: true
console.log(Object.prototype.__proto__ === null); // 输出: true
```

通过原型对象,可以实现方法的共享,提高性能,增强了代码的灵活性和可维护性,希望本文能帮助你更好地理解原型。

相关推荐
小二·37 分钟前
layui树形组件点击树节点后高亮的解决方案
前端·javascript·layui
Minions_Fatman38 分钟前
【layui】table的switch、edit修改
前端·javascript·layui
槑带可乐1 小时前
[可乐的随手记 - 6] 并发控制上传大量的文件 (worker + yield )
前端·javascript
小孙姐1 小时前
4——单页面应用程序,vue-cli脚手架
前端·javascript·vue.js
生椰拿铁You1 小时前
15 —— Webpack中的优化——前端项目使用CDN技术
前端·webpack
生椰拿铁You1 小时前
13 —— 开发环境调错-source map
前端
知野小兔1 小时前
【Angular】async详解
前端·javascript·angular.js
来啦来啦~1 小时前
vue项目实现动效交互---lottie动画库
前端·vue.js·交互
没了对象省了流量ii1 小时前
11.9K Star!强大的 Web 爬虫工具 FireCrawl:为 AI 训练与数据提取提供全面支持
前端·人工智能·爬虫
我的div丢了肿么办1 小时前
vue项目中如何加载markdown作为组件
前端·javascript·vue.js