目录
  1. 1. prototype原型
    1. 1.1. prototype与constructor
    2. 1.2. 显式原型与隐式原型
      1. 1.2.1. 内存结构
        1. 1.2.1.0.1. 总结:
  2. 1.3. 检查对象
    1. 1.3.1. in
    2. 1.3.2. hasOwnProperty()
  3. 1.4. 原型链
  • 2. 面试题
  • JavaScript中prototype原型

    prototype原型

    • 我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype。它默认指向一个Object空对象(即称为: 原型对象)

    prototype与constructor

    • 原型对象中有一个属性constructor, 它指向函数对象

    // 此处有一个Type对象,Type的prototype  -->>   Type的prototype(即Type的原型对象)
    // 同时Type的原型对象一个 constructor -->> Type,找到Type
    console.log(Date.prototype.constructor===Date) // ture
    function Fun () {//alt + shift +r(重命名rename)

    }
    console.log(Fun.prototype.constructor===Fun) // ture

    显式原型与隐式原型

    • 每个函数function都有一个prototype,即显式原型(属性)
    • 每个实例对象都有一个__proto__,可称为隐式原型(属性)
    • 原型就是一个对象,和其他对象没有任何区别,可以通过构造函数来获取原型对象。 和其他对象一样我们可以添加修改删除原型中的属性,也可以修改原型对象的引用。
      • 构造函数. prototype
      • 指向该构造函数的原型对象,我们可以通过__proto__来访问该属性
      • 对象的隐式原型的值为其对应构造函数的显式原型的值
    //定义一个构造函数
    function MyClass(){

    }
    var mc = new MyClass();
    var mc2 = new MyClass();
    console.log(MyClass.prototype);
    console.log(mc.__proto__);
    console.log(mc2.__proto__);
    console.log(mc2.__proto__ == MyClass.prototype); // true

    内存结构

    • 显示原型与隐式原型同时保存相同的地址值
    //定义构造函数
    function Fn() { // 内部语句: this.prototype = {}

    }

    //创建实例对象
    var fn = new Fn() // 内部语句: this.__proto__ = Fn.prototype
    console.log(fn.__proto__)
    console.log(Fn.prototype===fn.__proto__) // true
    // 所有的函数都是Function的实例对象
    console.log(Fn.__proto__ == Function.prototype); // true
    //给原型添加方法
    Fn.prototype.test = function () {
    console.log('test()')
    }
    //通过实例调用原型的方法
    fn.test()

    内存结构图示:

    总结:
    • 函数的prototype属性: 在定义函数时自动添加的, 默认值是一个空Object对象

      • 对象的__proto__属性: 创建对象时自动添加的, 默认值为构造函数的prototype属性值
      • 程序员能直接操作显式原型, 但不能直接操作隐式原型(ES6之前)
    • 原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中。
    • 当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用

    //定义一个构造函数
    function MyClass(){

    }
    //向MyClass的原型中添加属性a
    MyClass.prototype.a = 123;

    //向MyClass的原型中添加一个方法
    MyClass.prototype.sayHello = function(){
    console.log("hello");
    };

    var mc = new MyClass();
    var mc2 = new MyClass();
    var mc3 = new MyClass();

    //向mc中添加a属性
    mc.a = "我是mc中的a";

    console.log(mc.a);
    console.log(mc2.a);
    mc3.sayHello();

    • 因此以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了。

    每一个对象都有原型,包括原型对象也有原型。特殊的是 Object的原型对象没有原型。

    检查对象

    in

    使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true

    /*
    * 创建一个构造函数
    */
    function MyClass(){

    }

    //向MyClass的原型中添加一个name属性
    MyClass.prototype.name = "我是原型中的名字";

    var mc = new MyClass();
    mc.age = 18;

    console.log("name" in mc);

    hasOwnProperty()

    可以使用对象的hasOwnProperty()来检查对象自身中是否含有该属性,使用该方法只有当对象自身中含有属性时,才会返回true

    /*
    * 创建一个构造函数
    */
    function MyClass(){

    }

    //向MyClass的原型中添加一个name属性
    MyClass.prototype.name = "我是原型中的名字";

    var mc = new MyClass();
    mc.age = 18;
    //检查是否有age属性
    console.log(mc.hasOwnProperty("age"));
    //检查是否有name属性
    console.log(mc.hasOwnProperty("name"));

    原型链

    基于我们上边所说的,每个对象都有原型对象

    • 原型对象也是对象,所以它也有原型,当我们使用一个对象的属性或方法时,会现在自身中寻找
      • 自身中如果有,则直接使用
      • 如果没有则去原型对象中寻找,如果原型对象中有,则使用
      • 如果没有则去原型的原型中寻找,直到找到Object对象的原型
      • Object对象的原型没有原型,如果在Object原型中依然没有找到,则返回undefined

    /*
    * 创建一个构造函数
    */
    function MyClass(){

    }

    //向MyClass的原型中添加一个name属性
    MyClass.prototype.name = "我是原型中的名字";

    var mc = new MyClass();
    mc.age = 18;

    console.log(mc.__proto__.hasOwnProperty("hasOwnProperty"));
    //获取原型的原型
    console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));

    //这里已经找到头,到object
    console.log(mc.__proto__.__proto__.__proto__);

    上图可以看出,如果找不到可以到原型的原型去寻找,找到object以后,则不存在原型

    • 所有函数都是Function的实例(包含Function)
    console.log(Function.__proto__===Function.prototype) // true
    • Object的原型对象是原型链尽头
    console.log(Object.prototype.__proto__) // null

    面试题

    1. 问打印结果分别是多少?
    function A () {

    }
    A.prototype.n = 1

    var b = new A()

    A.prototype = {
    n: 2,
    m: 3
    }

    var c = new A()
    console.log(b.n, b.m, c.n, c.m) // 1 undefined 2 3

    文章作者: Jachie Xie
    文章链接: https://xjc5772.github.io/2020-02/16/%E5%AD%A6%E4%B9%A0/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0/JS/JavaScript%E4%B8%ADprototype%E5%8E%9F%E5%9E%8B/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 XJC&Blog
    打赏
    • 微信
    • 支付宝

    评论