NoteDeep
JavaScript 是基于原型的语言 (prototype-based language)。每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,这种关系被称为原型链 (prototype chain).

实例:
//构造器函数
function Person(name, age) { this.name = name;
this.age = age; }
var person1 = new Person('bro',10);

获得一个对象的原型:
Object.getPrototypeOf(obj) 或者 obj.__proto__

构造器函数,顾名思义就是用来创建对象的,而它的prototype属性就是告诉我们,创建对象所用的原型是什么?
构造器函数的prototype属性 指向原型对象,obj.__proto__也指向原型对象。只有函数对象有prototype属性。


Object和Function互为实例对象是不对的,Object是Function的实例对象, Function.prototype是Object的实例对象。Function是Function的实例对象

每个对象实例都具有 constructor 属性,它指向创建该实例的构造器函数。

当我们访问一个属性值的时候, 它会沿着原型链向上查找,
直到找到或者到Object.prototype.__proto__(为null)截止.
Object.prototype.__proto__ === null

person1.__proto__ === Object.getPrototypeOf(person1) === Person.prototype

对象person1的原型和Person函数的prototype属性指向同一个对象,即原型对象。

Person.__proto__ === Object.__proto__ === Function.__proto__ === Function.prototype

Person 是构造器函数,函数是对象。
Object、Function 也是构造器函数
因为一切函数都是Function的实例,所以这些函数的原型都是 Function.prototype

Function.prototype.__proto__ === Object.prototype === Person.prototype.__proto__

因为:Function.prototype是Object的对象。
Person.prototype也是Object的对象。

Object.constructor === Function === Function.constructor

实例对象的constructor属性指向其构造函数, person1.constructor = Person

Person===Person.prototype.constructor === person1.constructor

因为Person的原型对象 就是通过Person函数创建的。






调用 person1 的“实际定义在 Object 上”的方法时,会发生什么?比如:
person1.valueOf()
这个方法仅仅返回了被调用对象的值。在这个例子中发生了如下过程:
  • 浏览器首先检查,person1 对象是否具有可用的 valueOf() 方法。
  • 如果没有,则浏览器检查 person1 对象的原型对象(即 Person)是否具有可用的 valueof() 方法。
  • 如果也没有,则浏览器检查 Person() 构造器的原型对象(即 Object)是否具有可用的 valueOf() 方法。Object 具有这个方法,于是该方法被调用

从某个角度而言,类其实是一个抽象概念,构造器可以理解为一个类。

constructor 属性

每个对象实例都具有constructor 属性,它指向创建该实例的构造器函数。

例如,在控制台中尝试下面的指令:person1.constructor person2.constructor 都将返回 Person() 构造器,因为该构造器包含这些实例的原始定义。 一个小技巧是,你可以用这个构造器创建另一个对象实例。毕竟构造器是一个函数,故可以通过圆括号调用;只需在前面添加 new 关键字,便能将此函数作为构造器使用。
var person3 = new person1.constructor('Karen', 26');

通常你不会去用这种方法创建新的实例;但如果你刚好因为某些原因没有原始构造器的引用,那么这种方法就很有用了。

此外,constructor属性还有其他用途。比如,想要获得某个对象实例的构造器的名字,可以这么用:
instanceName.constructor.name
具体地,像这样:
person1.constructor.name

修改原型

事实上,一种极其常见的对象定义模式是,在构造器(函数体)中定义属性、在 prototype属性上定义方法。如此,构造器只包含属性定义,而方法则分装在不同的代码块,代码更具可读性。例如:
// 构造器及其属性定义 function Test(a,b,c,d) { // 属性定义 }; // 定义第一个方法 Test.prototype.x = function () { ... } // 定义第二个方法 Test.prototype.y = function () { ... } // 等等……





评论列表

    person1.__proto__ === Object.getPrototypeOf(person1) === Person.prototype
    Person.__proto__ === Object.__proto__ === Function.__proto__ === Function.prototype
    Function.prototype.__proto__ === Object.prototype === Person.prototype.__proto__
    Object.constructor === Function === Function.constructor
    Person===Person.prototype.constructor === person1.constructor
    constructor 属性