构造函数、原型对象、实例、隐式原型的理解

(欢迎一起探讨,如果有什么地方写的不准确或是不正确也欢迎大家指点,最后留了一个疑问,欢迎各位大神来探讨~)

PS:

  • 内容中的__proto__可能会被markdown语法导致显示为proto。
  • 建议将构造函数中的方法都定义到构造函数的原型中,由该构造函数创建的实例的方法都会指向同一个方法。(在内部声明的话,每创建一个实例都会重新实例化函数,每个实例中的函数的指向是不同的;如果定义在全局中,且有很多方法,这样毫无封装性可言。)

一、属性和方法

构造函数可以定义三种属性和方法:

对象属性/对象方法:在构造函数中定义的属性或方法

静态属性/静态方法:构造函数的静态属性或方法

原型属性/原型方法:构造函数的原型的属性或方法

(以下,构造函数的对象属性和对象方法 简称 对象属性和对象方法,构造函数的静态属性和方法 简称 静态属性和静态方法,构造函数的原型的属性和方法 简称 原型属性和原型方法)

实例:

function Shape() {
  // 对象属性和对象方法
  this.color = ‘red‘;
  this.show = function(){
    console.log(‘show‘)
  }
}

// 静态属性和静态方法
Shape.type = ‘auto‘
Shape.printing = function(){
  console.log(‘Shape‘)
}

// 原型属性和原型方法
Shape.prototype.area = ‘unknow‘
Shape.prototype.move = function() {
  console.info(‘move‘);
};

// 实例
var rect = new Shape();

console.log(rect.color) // red
console.log(rect.show()) // show

console.log(rect.area) // unknow
console.log(rect.move()) // move

console.log(Shape.type) //auto
console.log(Shape.printing()) //Shape

console.log(rect.type)  // undefined
console.log(rect.printing()) //undefined

构造函数的对象属性和对象方法、原型属性和原型方法,对应的实例都可以调用,构造函数本身调用失败,会提示undefined;

构造函数的静态属性和静态方法,对应的实例调用失败,会提示undefined,但是可由构造函数本身调用。

调用属性、方法 对象属性和对象方法 原型属性和原型方法 静态属性和静态方法
构造函数 undefined undefined 可以得到
实例 可以得到 可以得到 undefined

二、prototype、constructor、proto

在以上的基础上,再实例化一个新的对象和普通函数。

var circle = new Shape();

function test(){
  console.log(‘test‘)
}

console.log(Shape.prototype,‘\n‘,Shape.constructor,‘\n‘,Shape.__proto__)
console.log(Shape.prototype.constructor,‘\n‘,Shape.prototype.constructor ===Shape)

console.log(rect.prototype,‘\n‘,rect.constructor,‘\n‘,rect.__proto__)
console.log(rect.prototype.constructor,‘\n‘,rect.prototype.constructor ===rect)

console.log(circle.prototype,‘\n‘,circle.constructor,‘\n‘,circle.__proto__)
console.log(circle.prototype.constructor,‘\n‘,circle.prototype.constructor ===circle)

console.log(test.prototype,‘\n‘,test.constructor,‘\n‘,test.__proto__)
console.log(test.prototype.constructor,‘\n‘,test.prototype.constructor ===test)

Shape的constructor(构造器)指向Function,proto(隐式原型)指向 ? () { [native code] }。

实例的原型均为undefined,constructor(构造器)指向Shape构造函数(代表是Shape的实例),proto(隐式原型)指向Shape的原型对象。

test的原型指向一个包含construct和__proto__的对象,它的constructor(构造器)指向Function,proto(隐式原型)指向 ? () { [native code] }。

指向 prototype constructor proto prototype.constructor(如果有值,与本身严格比较)
构造函数 构造函数的原型 Function ? () { [native code] } 其本身
实例 undefined 构造其本身的构造函数 构造其本身的构造函数的原型 Cannot read property ‘constructor‘ of undefined
普通函数 一个包含construct和__proto__的对象 Function ? () { [native code] } 其本身

综上可以知道

  • ? () { [native code] } 是Function的原型。
  • 实例的constructor(构造器)都指向构造其本身的构造函数。
  • 而__proto__,均指向构造其本身的构造函数的原型。

验证一下。

console.log(Shape.__proto__ === Shape.constructor.prototype) // true
console.log(Shape.__proto__ === Function.prototype) // true

console.log(rect.__proto__ === rect.constructor.prototype) // true
console.log(rect.__proto__ === Shape.prototype) // true

console.log(circle.__proto__ === circle.constructor.prototype) // true
console.log(circle.__proto__ === Shape.prototype) // true

console.log(test.__proto__ === test.constructor.prototype) // true
console.log(test.__proto__ === Function.prototype) // true


每个函数都有prototype属性。

实例都有一个constructor(构造函数)属性,该属性指向构造它的构造函数。

调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。

即__proto__属性。

默认情况下,所有原型对象都会自动获得一个constructor属性,这个属性包含一个指向prototype属性所在函数的指针。

如:Shape.prototype.constructor === Shape

prototype就是通过调用构造函数而创建的那个对象实例的原型对象。使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。

(重点在 共享

PS:

可以通过hasOwnProperty判断一个对象是否包含自定义属性而不是原型链上的属性。

如果是通过原型添加的属性和方法,实例中虽然不包含属性和方法,但是却可以调用构造函数的原型中定义的方法。这是通过查找对象属性(proto)的过程来实现的。

实例通过__proto__属性去该构造函数的原型中去找属性/方法,如果没有,该构造函数的原型通过__proto__属性去找构造它的构造函数的原型中去找,以此类推。这个通过__proto__属性连接起来的链条就是原型链。原型链最终得到的值是null。

// 此处代表原型链
console.log(circle.__proto__,circle.__proto__ === Shape.prototype) // true
console.log(circle.__proto__.__proto__,circle.__proto__.__proto__ === Object.prototype) // true
console.log(circle.__proto__.__proto__.__proto__) // null

/*
以上代码可以理解为

circle.__proto__ === Shape.prototype
Shape.prototype.__proto__ === Object.prototype
*/
// 已经知道constructor得到的是“构造”关系
// 那么__proto__形成的是什么关系?

// 或许会认为出现以下情况,注意:__proto__查找的是原型
console.log(circle.__proto__,circle.__proto__ === Function.prototype) // false

console.log(Shape.__proto__ === Function.prototype) // true
console.log(Function.__proto__ === Object.prototype) // false
console.log(Function.__proto__ === Function.prototype) // true

console.log(circle.__proto__.__proto__,circle.__proto__.__proto__ === Function.prototype) // false

下面来验证一下~

function Shape() {
  this.color = ‘red‘;
  this.show = function(){
    console.log(‘show‘);
  }
}

Shape.prototype.area = ‘unknow‘
Shape.prototype.move = function() {
  console.info(‘move‘);
};

function Rect(){
  Shape.call(this);
  this.color = ‘pink‘;
}

Rect.prototype = new Shape();
Rect.prototype.constructor = Rect;
Rect.prototype.name = ‘Rect‘;

var rect = new Rect();
console.log(rect); // Rect {color: "pink", show: ?}
console.log(rect.__proto__) // Shape {color: "red", show: ?, constructor: ?, name: "Rect"}
console.log(rect.__proto__.__proto__) // {area: "unknow", move: ?, constructor: ?}

由以上代码得出,__proto__得到的是继承关系~



额外:

那么Function呢?

console.log(Function.prototype) // ? () { [native code] }

console.log(Function.prototype.constructor === Function) // true

console.log(Function.constructor) // ? Function() { [native code] }  会不会是其本身?
console.log(Function.constructor  === Function) // true
// 为什么???

// 根据以上输出,可以认为它的__proto__就是它的prototype
console.log(Function.__proto__ === Function.constructor.prototype) // true
console.log(Function.__proto__ === Function.prototype) // true

// 检测
console.log(Function instanceof Object) // true

// 疑问!?为什么都指向Function呢?
console.log(Function.constructor) // ? Function() { [native code] }
console.log(Object.constructor) // ? Function() { [native code] }

原文地址:https://www.cnblogs.com/hiuman/p/9543792.html

时间: 2024-10-27 19:58:51

构造函数、原型对象、实例、隐式原型的理解的相关文章

函数原型prototype以及对象的隐式原型__prot0__的基本了解

prototype原型: 一. 函数与对象的关系    1. 函数是对象的一种(函数是对象类型)        例: function fn1(){.........}           console.log(fn1 instanceof Object);           返回true,说明函数(fn1)是对象类型. 2. 对象是由函数创建的       例: var obj = new Object();           var arr = new Array(3);       

JavaScript中显式原型和隐式原型的联系

显式原型:prototype 隐式原型:__proto__ 1.显式原型和隐式原型是什么? 在js中万物皆对象,方法(Function)是对象,方法的原型(Function.prototype)是对象,对象具有属性(__proto__)称为隐式原型,对象的隐式原型指向构造该对象的构造函数的显式原型. 方法(Function)是一个特殊的对象,除了和其他对象一样具有__proto__属性以外,它还有一个自己特有的原型属性(prototype),这个属性是一个指针,指向原型对象.原型对象也有一个属性

JS高阶---显式原型和隐式原型

前言: 1.函数对象即函数的prototype原型属性指向原型对象,在创建函数时便存在,默认为空Object 2.实例对象的__proto__隐式原型在实例化创建实例时产生,值等于构造函数的显式prototype原型属性的值 3.开发时程序员操作显式原型在原型prototype上添加方法,不能直接操作隐式原型__proto__(ES6之前) 大纲: [主体] (1)每个函数都有一个prototype原型属性,称之为显式原型属性或显式原型 (2)每个实例对象都有一个__prop__原型属性,称之为

深入理解javascript原型和闭包(4)——隐式原型

转载于http://www.cnblogs.com/wangfupeng1988/p/3979290.html 注意:本文不是javascript基础教程,如果你没有接触过原型的基本知识,应该先去了解一下,推荐看<javascript高级程序设计(第三版)>第6章:面向对象的程序设计. 上节已经提到,每个函数function都有一个prototype,即原型.这里再加一句话——每个对象都有一个__proto__,可成为隐式原型. 这个__proto__是一个隐藏的属性,javascript不希

深入理解js——隐式原型

每个函数都有一个prototye(原型),而每个对象都有一个_proto_,可成为隐式原型. _proto_是一个隐藏的属性,javascript不希望开发者用到这个属性值,有的低版本浏览器甚至不支持这个属性值.所以你在Visual Studio 2012这样很高级很智能的编辑器中,都不会有__proto__的智能提示,但是你不用管它,直接写出来就是了. var obj={},去控制台输出obj._proto_,会发现obj.__proto__和Object.prototype的属性一样.因为o

理解javascript原型和作用域系列(4)——隐式原型

上节已经提到,每个函数function都有一个prototype,即原型.这里再加一句话——每个对象都有一个__proto__,可成为隐式原型. 这个__proto__是一个隐藏的属性,javascript不希望开发者用到这个属性值,有的低版本浏览器甚至不支持这个属性值.所以你在Visual Studio 2012这样很高级很智能的编辑器中,都不会有__proto__的智能提示,但是你不用管它,直接写出来就是了. 上面截图看来,obj.__proto__和Object.prototype的属性一

浅析JS原型对象&amp;实例对象&amp;构造函数(转)

浅析原型对象,实例对象,构造函数的关系 原文地址:JS面向对象-原型对象,实例对象,构造函数的关系(http://blog.csdn.net/u014205965/article/details/45798861) 因为最根上的object拥有一个prototype属性,而js中所有的对象又都继承自object,所以js中所有的对象都拥有一个prototype属性,而在js中函数也是对象,所以js中每个函数也都有一个prototype属性. 例如:function Person(){...} 和

JavaScirpt中的原型,原型对象和原型链

一.什么是原型呢? 我们创建每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象.(即prototype即为函数的原型该原型指向的是一个原型对象) 二.什么是原型对象呢? 我们创建每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象(即原型对象).而这个对象的用途是包含 可以由特定类型的所有 实例 共享的属性和方法.(字面意思prototype就是通过调用构造函数而创建的实例对象的原型对象) 使用原型对象的好处是可以让所有的对象实例(实

构造函数,原型对象,实例对象

一.构造函数,原型对象,实例对象 1.1 基本概念 1.对象: 属性和方法的集合,即变量和函数的封装. 调用构造函数产生的实例对象, 每个对象都有一个__proto__属性,指向这个对象的构造函数的原型对象. 2.构造器函数: 用于创建对象的函数,通过new关键字生成对象. 函数名一般首字母大写的. 每创建一个函数, 该函数都会自动带有一个prototype属性.该属性是一个指针,指向一个对象,该对象称之为原型对象(后期我们可以使用这个原型对象帮助我们在js中实现继承) 3.原型对象: 默认有一