前端知识点---原型-原型链(javascript)

06-01 1391阅读

文章目录

  • 原型
  • 原型链:
  • 实际应用
  • 面试题回答

    原型

    原型:每个函数都有prototype属性 称之为原型

    因为这个属性的值是个对象,也称为原型对象

    只有函数才有prototype属性

    作用:

    1.存放一些属性和方法

    2.在Javascript中实现继承

    const arr = new Array(1, 2, 3, 4)
    console.log(arr.reverse)
    

    为什么创建好了就可以使用这些方法呢? 就是原型的存在

    Array构造函数也是一个函数 , 只要是函数就有个原型 就是Array.prototype

    打开mdn

    前端知识点---原型-原型链(javascript)

    在这个原型身上已经挂载了很多方法, 这些方法是可以给所有的数组实例去使用的

    为什么实例可以去使用这些方法呢 , 是因为_porto_

    每个对象都有_proto_属性

    作用: 这个属性指向它的原型对象

    前端知识点---原型-原型链(javascript)

    原型链:

    前端知识点---原型-原型链(javascript)

    关系总结:

    构造函数 -> prototype -> 构造函数的原型对象

    构造函数的原型对象 -> proto -> Object.prototype

    Object.prototype -> proto -> null(原型链的终点)

    代码演示:

    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
    const p = new Person("张三", 25);
    // p 的 __proto__ 指向 Person.prototype
    console.log(p.__proto__ === Person.prototype); // true
    // Person.prototype 的 __proto__ 指向 Object.prototype
    console.log(Person.prototype.__proto__ === Object.prototype); // true
    // Object.prototype 是原型链的终点
    console.log(Object.prototype.__proto__); // null
    

    解释:

    Person.prototype.proto 确实指向 Object.prototype。

    Object.prototype 没有更上层的原型,所以它的 proto 是 null。

    所以,构造函数的原型对象最终的 proto 是指向 Object.prototype,而 Object.prototype 的 proto 是 null,这是原型链的终点。

    实际应用

    1. 共享方法,减少内存开销

      在大型项目中,如果每个实例都独立创建相同的方法,会占用大量内存。原型可以让多个实例共享方法,从而提高性能。

    示例:创建对象的优化

    function User(name) {
        this.name = name;
    }
    // 将方法放在 prototype 上,所有实例共享
    User.prototype.sayHello = function() {
        console.log("Hello, my name is " + this.name);
    };
    let user1 = new User("Alice");
    let user2 = new User("Bob");
    user1.sayHello(); // 输出: Hello, my name is Alice
    user2.sayHello(); // 输出: Hello, my name is Bob
    

    ✅ 优点:所有 User 实例共享 sayHello 方法,而不是每次创建实例都生成新的方法,节省内存。

    1. 继承与扩展

      在项目中,多个对象可能有相似的行为,我们可以利用原型继承来减少代码重复,提高复用性。

    示例:父类与子类继承

    function Animal(name) {
        this.name = name;
    }
    // 父类原型方法
    Animal.prototype.speak = function() {
        console.log(this.name + " makes a sound");
    };
    // 子类
    function Dog(name, breed) {
        Animal.call(this, name); // 继承属性
        this.breed = breed;
    }
    // 继承父类的方法
    Dog.prototype = Object.create(Animal.prototype);
    Dog.prototype.constructor = Dog;
    // 添加子类特有方法
    Dog.prototype.bark = function() {
        console.log(this.name + " barks!");
    };
    let dog1 = new Dog("Buddy", "Labrador");
    dog1.speak(); // 输出: Buddy makes a sound
    dog1.bark();  // 输出: Buddy barks!
    

    ✅ 优点:

    Dog 继承了 Animal 的 speak 方法,无需重复定义。

    Dog.prototype 还能额外扩展 bark 方法,增强灵活性。

    3. 扩展原生对象

    有时候我们需要扩展 JavaScript 自带的对象,比如 Array、String 等。

    示例:扩展 Array.prototype

    Array.prototype.sum = function() {
        return this.reduce((total, num) => total + num, 0);
    };
    let numbers = [1, 2, 3, 4, 5];
    console.log(numbers.sum()); // 输出: 15
    

    ✅ 优点:给所有数组对象增加 sum 方法,方便项目中复用。

    ⚠️ 注意:扩展原生对象可能会影响第三方库,应谨慎使用!

    1. 实现类的私有属性

      在 ES5 时代,我们可以通过原型和闭包结合,模拟私有变量,防止外部直接访问。

    示例:使用闭包模拟私有属性

    function Person(name) {
        let _age = 25; // 私有变量,外部无法直接访问
        this.name = name;
        this.getAge = function() {
            return _age;
        };
    }
    let p1 = new Person("Alice");
    console.log(p1.name);  // Alice
    console.log(p1.getAge()); // 25
    console.log(p1._age);  // undefined,无法直接访问
    

    ✅ 优点:保护 _age 变量不被外部随意修改,提高安全性。

    1. 结合原型模式和单例模式

      在实际开发中,我们可能希望某个对象只存在一个实例(比如配置管理、数据库连接池等)。可以结合原型模式和单例模式来实现。

    示例:全局配置管理

    const Config = (function() {
        function Config() {
            this.theme = "dark";
            this.language = "en";
        }
        let instance;
        
        Config.getInstance = function() {
            if (!instance) {
                instance = new Config();
            }
            return instance;
        };
        return Config;
    })();
    let config1 = Config.getInstance();
    let config2 = Config.getInstance();
    console.log(config1 === config2); // true,说明是同一个实例
    

    ✅ 优点:

    只创建一个 Config 实例,避免重复初始化配置,提高效率。

    总结

    应用场景代码示例主要作用
    方法共享User.prototype.sayHello让多个实例共享方法,节省内存
    继承与扩展Dog.prototype = Object.create(Animal.prototype)复用父类方法,减少代码重复
    扩展原生对象Array.prototype.sum添加全局通用方法,增强功能
    私有属性let _age = 25;保护数据,防止外部修改
    单例模式Config.getInstance()确保对象全局唯一

    在实际项目中,合理运用原型能有效提高代码复用性、减少冗余,并优化性能! 🚀

    面试题回答

    • 1.原型:函数都有prototype属性,称之为原型,也称为原型对象N原型可以放一些属性和方法,共享给实例对象使用

      原型可以做继承

    • 2.原型链:对象都有_proto 属性,这个属性指向它的原型对象,原型对象也是对象,也有_proto 属性,指向原型对象的原型对象,这样一层一层形成的链式结构称为原型链,最顶层找不到则返回 null
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码