原型 原型链

689 阅读3分钟


普通对象与函数对象

普通对象
普通的对象:只有__proto__属性(指向其原型链),没有prototype属性。


函数对象
Object 、Function 是 JS 自带的函数对象。凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象。

函数对象有__proto__及,每个函数函数对象都会有一个默认的prototype属性(指向原型对象)。

Function、Object、Array、Date、String、自定义函数

特例: Function.prototype(是原型对象,却是函数对象)

    
    console.log(Array) //ƒ Array() { [native code] }
    console.log(Array.__proto__ === Function.prototype) //true
    console.log(Array.__proto__) //ƒ () { [native code] }

Array是函数对象,是Function的实例对象,Array是通过newFunction创建出来的。因为Array是Function的实例,所以Array.__proto__ === Function.prototype

__proto__ 指向谁?

__proto__指向 取决于创建对象时的实现方式

prototype与__proto__的区别:

每个对象都有 __proto__ 属性,但只有函数对象才有 prototype 属性

        
        var obj = {}
        console.log(obj.__proto__)// Object {}
        console.log(obj.prototype)//undefined
        function Person() {

        }
        console.log(Person.__proto__) //function () {}
        console.log(Person.prototype) //Object {}

原型

1)构造函数中有一个属性:prototype,叫原型,是给我们程序员用的。
2)实例对象中有一个属性:__proto__,也叫原型,这个是给浏览器看的。
3)构造函数中的prototype和实例中的__proto__指向相同。
4)prototype的数据可以被实例对象访问和使用。

构造函数 Person

实例化对象 person1

原型对象 Person.prototype

实例是通过构造函数创建的。实例一创造出来就具有constructor属性(指向构造函数)和proto属性(指向原型对象),

构造函数中有一个prototype属性,这个属性是一个指针,指向它的原型对象

原型对象内部也有一个指针(constructor属性)指向构造函数:Person.prototype.constructor === Person;


        
        function Person(name) {
            this.name = name;
        }
        var person1 = new Person("nwd")
        console.log(person1.constructor)
        console.log(person1.constructor === Person)   // true
        console.log(Person.prototype.constructor === Person) // true
    

console如下


        
        function Person(name) {
            this.name = name;
        }
        var person1 = new Person("nwd")
        console.log(Person.prototype.constructor)
        console.log(Person === Person.prototype.constructor ) //true

console如下


        
        function Person(name) {
            this.name = name;
        }
        var person1 = new Person("nwd")
        console.log(person1.__proto__)
        console.log(Person.prototype)
        console.log(person1.__proto__ === Person.prototype) //true

console如下


注:构造函数 Person 的prototype,也是构造函数实例出来的对象person1的原型(它其实也是一个对象)


        
        function Person(name) {
            this.name = name;
        }
        var person1 = new Person("nwd")
        console.log(person1.constructor)
        console.log(person1.__proto__.constructor)
        console.log(person1.constructor === person1.__proto__.constructor) //true

console如下


原型链

每个实例对象(object)都有一个私有属性(称之为__proto__)指向它的原型对象(prototype)。该原型对象也有自己的原型对象,就这样组成了原型链.

__proto__是所有对象(包括函数)都有的,它叫做对象的原型,原型链就是靠它形成的。而__proto__的终点值时null。在查找对象属性时,先确定对象是否存在该对象,不存在会在原型链上查找,不会在自身的prototype上查找。

person1具有__proto__属性,指向Person.prototype
Person.prototype具有__proto__属性,指向Object.prototype
Object.prototype具有__proto__属性,指向null
console.log(person1.__proto__ === Person.prototype) // true
console.log(Person.prototype.__proto__ === Object.prototype) // true
console.log(Object.prototype.__proto__) // null

这些__proto__串起来,就构成了原型链,原型链的顶端为null


    function Person() {

    }
    console.log(Person.__proto__)
    console.log(Person.prototype)
    console.log(Person.prototype.__proto__)
    console.log(Object.prototype)
    console.log(Object.prototype.__proto__)


注:通过__ proto __形成原型链而非protrotype

原型链是实现继承的主要方法:

        function Person(sex) {
            this.sex = sex;
        }
        Person.prototype.getSex = function() {
        	console.log(this.sex)
        }
       	function Student(name) {
       		this.name = name
       	}
       	Student.prototype = new Person("男")

        Student.prototype.say = function() {
        	console.log(this.name)
        }
        var person1 = new Student("lihe")
        console.log(person1)

如下图


原型链关系如下:


        console.log(person1.__proto__ === Student.prototype) //true
        console.log(person1.__proto__)
        console.log(Student.prototype)
        console.log(Student)

        console.log(Student.prototype.__proto__ === Person.prototype) //true
        console.log(Student.prototype.__proto__)
        console.log(Person.prototype)

        console.log(Person.prototype.__proto__ === Object.prototype) //true
        console.log(Person.prototype.__proto__) 

        console.log(Object.prototype.__proto__ === null) //true