JavaScript——原型、原型链

原型

构造函数

1、let a = {} 等同于 let a = new Object() (a的构造函数是 Object 函数)

2、let a = [] 等同于 let a = new Array() (a的构造函数是 Array 函数)

3、function Foo {} 等同于 let Foo = new Function() (Foo 的构造函数是 Function 函数)

prototype

Javascript规定,每一个函数都有prototype的属性,叫做“原型”,prototype的所有属性和方法,都会被构造函数的实例继承,在开发的时候就可以把一些公用的属性和方法直接定义在prototype上。

  function Foo() { };
  let f = new Foo()
  console.log(Foo.prototype);// Object{} 
  console.log(f.prototype);//undefined

proto

每一个对象都有*proto*的属性,叫做“隐式原型”,只有对象才有的属性,prototype是只有函数才有的属性。每一个对象的proto,指向创建该对象的函数的prototype

  		//f是通过Foo构造出来的实例对象,那么
        function Foo() { };
        let f = new Foo()
        console.log(f.__proto__ === Foo.prototype);//true

在这里插入图片描述
可能会有疑问,Foo是函数为什么返回的f却是对象。

    console.log(Foo instanceof Object);//true
    console.log(Foo instanceof Function);//true

    console.log(Function instanceof Object);//true
    console.log(Object instanceof Function);//true

函数属于对象,同时函数也可以创建对象。

所有的函数本质上都是有Function创建出来的,在开头构造函数提到。

    let foo = new Function()
    console.log(foo.__proto__ === Function.prototype);//true
	//同理所有的对象本质上都是有Object创建出来的
    let obj = new Object()
    console.log(obj.__proto__ === Object.prototype);//true
constructor

每一个原型都有一个constructor属性constructor保存了指向function的一个引用。并且指向关联的构造函数,实例原型指向构造函数。

    function foo() { }
    let f = new foo()
    /*
      在前面构造函数提到过 foo其实是由 foo = new Function() 构造出来的
      所以foo的constructor属性指向顶层函数Function,而Function的constructor指向自己
     */
    console.log(foo.constructor);//ƒ Function() { [native code] }
	//同理f是foo构造出来的所以f.constructor指向foo
    console.log(f.constructor);//foo {}

    //又例如
    let obj = {}//等同于 obj = new Object()
    console.log(obj.constructor === Object);//true
    let arr = []//等同于 arr = new Array()
    console.log(arr.constructor === Array);//true

在这里插入图片描述

原型链

    function Foo() { }
    let f = new Foo()
    Foo.prototype.names = '张三'
    console.log(f.names);//张三
    Object.prototype.names = '张三'
    function Foo() { }
    let f = new Foo()
    console.log(f.names);//张三

我们看到实例对象f自身并没有name属性,但是却能访问到。

    Object.prototype.names = '张三'
    Function.prototype.age = '20'
    function Foo() { }
    let f = new Foo();
    console.log(f.names);//张三
    console.log(f.age);// undefined
    console.log(Foo.age);// 20
    // 注意
    console.log(Foo.prototype.__proto__ === Object.prototype);//true

f.age为什么会是undefined呢?Foo才是Function对象的一个实例,所以通过f.age应该可以访问到Function原型里的属性吧,但是new Foo()返回的是一个对象,他是Object的一个实例,是没有继承Function的,所以无法访问到age。而所有的对象都可以看做Objec的实例(let obj = new Object()),所以,

f.age => undefined;Foo.age => '20'

/*
  f是实例对象,访问names属性发现自身没有,就会去访问__proto__对应的prototype(也就是Foo的原型),
  还是发现没有,同理会查找Foo原型的__proto__,在向上找到Object的原型上有,结束。
*/

f.names => f.__proto__ => Foo.prototype => Foo.prototype.__proto__ => Object.prototype

在这里插入图片描述

​ 作为一个对象,当你访问其中某个属性或方法时,如果这个对象本身并没有这个属性或方法,那么Javascript引擎将会通过这个对象的__proto__属性所指向的上一个对象,并在哪个对象中查找指定的方法或属性,如果还是不能找到,那么久会继续通过哪个对象__proto__属性指向的对象向上查找,直到这个链表结束。

prototype最主要的方法就是将属性暴露成公用的,也就是说通过__proto__原型链继承,看两个例子。

        function Foo1(name, age) {
            this.name = name;
            this.sayHello = function () {
                console.log(this.name);
            }
        }
        let f1 = new Foo1('张三')
        let f2 = new Foo1('李四')
        console.log(f1.name);//张三
        console.log(f2.name);//李四
        console.log(f1.sayHello === f2.sayHello);//false

把方法和属性挂载到prototype上

        function Foo2(name, age) {
            this.name = name;
        }
		//把函数sayHello挂载到原型上
        Foo2.prototype.sayHello = function () {
            console.log(this.name);
        }
        let f3 = new Foo2('张三')
        let f4 = new Foo2('李四')
        console.log(f3.name);//张三
        console.log(f4.name);//李四
        console.log(f3.sayHello === f4.sayHello);//true
		//把对象info挂载到原型上
        Foo2.prototype.info = { name: '王五' }
        console.log(f3.info === f4.info);//true
        f3.info.name = '小明'
        console.log(f4.info.name);//小明

可以看出结果当我们构造的实例对象去访问同一个属性或方法时,其实是同一个,通过原型链继承了这些方法和属性。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值