代码改变世界

js-原型与原型链

2021-03-25 14:52  菩提本无树,明镜亦非台。  阅读(13)  评论(0)    收藏  举报

原型与原型链

  • JavaScript是一门基于原型的语言,在软件设计模式中,有一种模式叫做原型模式,JavaScript正是利用这种模式而被创建出来

  • 原型模式是用于创建重复的对象,同时又能保证性能,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。原型模式的目的是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象,也就是说利用已有的一个原型对象,可以快速地生成和原型对象一样的新对象实例

  • 原型:一个可以被复制(或者叫克隆)的一个类,通过复制原型可以创建一个一模一样的新对象,也可以说原型就是一个模板,在设计语言中更准确的说是一个对象模板

    1. 原型是定义了一些公用的属性和方法,利用原型创建出来的新对象实例会共享原型的所有属性和方法
    // 创建原型
    var Person = function(name){
        this.name = name;
    };
    
    // 原型的方法
    Person.prototype.sayHello = function(){
       console.log(this.name+",hello");
    };
    
    // 实例化创建新的原型对象,新的原型对象会共享原型的属性和方法
    var person1 = new Person("zhangsan");
    var person2 = new Person("lisi");
    
    // zhangsan,hello
    person1.sayHello();
    // lisi,hello
    person2.sayHello();
    
    1. 严格模式下,原型的属性和方法还是会被原型实例所共享的
    // 开启严格模式,原型的属性和方法还是会被原型实例所共享的
    "use strict";
    
    // 创建原型
    var Person = function(name){
        this.name = name;
    };
    
    // 原型的方法
    Person.prototype.sayHello = function(){
       console.log(this.name+",hello");
    };
    
    // 实例化创建新的原型对象,新的原型对象会共享原型的属性和方法
    var person1 = new Person("zhangsan");
    var person2 = new Person("lisi");
    
    // zhangsan,hello
    person1.sayHello();
    // lisi,hello
    person2.sayHello();
    
    1. 通过原型创建的新对象实例是相互独立的,为新对象实例添加的方法只有该实例拥有这个方法,其它实例是没有这个方法的
    // 创建原型
    var Person = function(name){
        this.name = name;
    };
    
    // 原型的方法
    Person.prototype.sayHello = function(){
       console.log(this.name+",hello");
    };
    
    // 实例化创建新的原型对象,新的原型对象会共享原型的属性和方法
    var person1 = new Person("zhangsan");
    var person2 = new Person("lisi");
    
    // zhangsan,hello
    person1.sayHello();
    // lisi,hello
    person2.sayHello();
    
    
    // 为新对象实例添加方法
    // 通过原型创建的新对象实例是相互独立的
    person1.getName = function(){
       console.log(this.name);
    }
    
    // zhangsan
    person1.getName();
    // Uncaught TypeError: person2.getName is not a function
    person2.getName();
    
    1. 原型总结:
    1、所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象
    2、所有函数都有一个prototype(原型)属性,属性值是一个普通的对象
    3、所有引用类型的__proto__属性指向它构造函数的prototype
    
    1. 函数的原型prototype:函数才有prototype,prototype是一个对象,指向了当前构造函数的引用地址
    2. 函数的原型对象__proto__:所有对象都有__proto__属性, 当用构造函数实例化(new)一个对象时,会将新对象的__proto__属性指向 构造函数的prototype
    3. 所有的原型对象都会自动获得一个 constructor(构造函数)属性,这个属性(是一个指针)指向 prototype 属性所在的函数(Person)
    4. 实例的构造函数属性(constructor)指向构造函数 :person1.constructor == Person
    5. 原型对象(Person.prototype)是 构造函数(Person)的一个实例
    6. 原型的分类:
    - 隐式原型(_proto_):上面说的这个原型是JavaScript中的内置属性[[prototype]],此属性继承自object对象,在脚本中没有标准的方式访问[[prototype]],但Firefox、Safari和Chrome在每个对象上都支持一个属性_proto_,隐式原型的作用是用来构成原型链,实现基于原型的继承
    - 显示原型(prototype):每一个函数在创建之后,便会拥有一个prototype属性,这个属性指向函数的原型对象,显示原型的作用是用来实现基于原型的继承与属性的共享
    

二、原型与原型链的常见面试题

  • 谈谈你对原型的理解?
在 JavaScript 中,每当定义一个对象(函数也是对象)时候,对象中都会包含一些预定义的属性。其中每个函数对象都有一个prototype 属性,这个属性指向函数的原型对象,使用原型对象的好处是所有对象实例共享它所包含的属性和方法
  • 什么是原型链?原型链解决的是什么问题?
- 原型链解决的主要是继承问题
- 每个对象拥有一个原型对象,通过 proto 指针指向其原型对象,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向 null(Object.proptotype.__proto__指向的是null)。这种关系被称为原型链(prototype chain),通过原型链一个对象可以拥有定义在其他对象中的属性和方法
- 构造函数 Parent、Parent.prototype 和 实例 p 的关系如下:(p.__proto__ === Parent.prototype)
  • prototype 和 proto 区别是什么?
- prototype是构造函数的属性
- __proto__是每个实例都有的属性,可以访问 [[prototype]] 属性
- 实例的__proto__与其构造函数的prototype指向的是同一个对象