Js中Prototype、__proto__、Constructor、Object、Function关系介绍总结

简介: 1.js的对象都拥有内部属性 [[prototype]] 指向其原型对象。[[prototype]] 被称为原型属性。 2 内部属性不可以直接访问.error: obj[[prototype]],但是可以间接访问 [[prototype]]

Prototype

1 js的对象都拥有内部属性 [[prototype]] 指向其原型对象。[[prototype]] 被称为原型属性。

2 内部属性不可以直接访问.error: obj[[prototype]],但是可以间接访问 [[prototype]]

a ECMA:标准对象原型访问器Object.getPrototype(object)(到目前为止只有Firefox和chrome实现了此访问器);

b 非标准访问器:__proto__(除了IE)

c obj.constructor.prototype

js的一切皆是对象,所以 函数也是对象.又因为对象拥有内部属性 [[prototype]],所以
函数也拥有内部属性 [[prototype]].

其次:函数同时拥有属性 prototype.prototype属性和 [[prototype]]并非同一个属性。

prototype属性指向一个对象,称为原型对象。所以:一个函数的原型属性(function’s prototype property ) 和函数实际的原型(prototype)没有关系

原型对象的作用:当函数fn被用作构造函数时,其所创建的所有实例的内部属性 [[prototype]] 指向 fn 的 prototype属性。

原型的作用:

1 构建原型链

当对象调用某个方法时,如果其本身不存在此方法,就会往其原型中寻找,直到原型链的顶端

原型链的作用:多个实例都需要的方法可以被抽出放到原型中,从而只需要定义一次,实现多个对象共享方法

Constructor

JS的所有对象都拥有constructor属性,指向其构造函数。函数的原型对象也是对象,所以原型对象也拥有constructor属性。并且JS定下了规则:

fn.prototype.constructor == fn;

即: 函数的prototype属性的constructor字段,指向当前prototype属性的拥有者,也就是构造函数本身

由 fn.prototype.constructor == fn;推导出来的结论:构造函数的实例的 constructor属性 指向其构造函数

推导:

var a = new fn();

首先在a本身寻找:没有找到 constructor属性.再往原型链向上查找,找到a的原型,也就是 fn.prototype,发现了 constructor属性。所以就相当于 构造函数的实例的 constructor属性始终指向其构造函数

Prototype、__proto__与Object、Function关系介绍

Function、Object:Js自带的函数对象

prototype,每一个函数对象都有一个显示的prototype属性,它代表了对象的原型(Function.prototype函数对象是个例外,没有prototype属性)

__proto__:每个对象都有一个名为__proto__的内部隐藏属性,指向于它所对应的原型对象(chrome、firefox中名称为__proto__,并且可以被访问到)。原型链正是基于__proto__才得以形成(note:不是基于函数对象的属性prototype)。

关于上面提到的函数对象,我们来看以下例子,来说明:

var o1 = {};
var o2 =new Object();
function f1(){}
var f2 = function(){}
var f3 = new Function('str','console.log(str)');
f3('aabb');   // aabb
console.log('typeof Object:'+typeof Object);            //function
console.log('typeof Function:'+typeof Function);        //function
console.log('typeof o1:'+typeof o1);   //object
console.log('typeof o2:'+typeof o2);   //object
console.log('typeof f1:'+typeof f1);   //function
console.log('typeof f2:'+typeof f2);   //function
console.log('typeof f3:'+typeof f3);   //function

通常我们认为o1、o2是对象,即普通对象;f1、f2、f3为函数。但是其实函数也是对象,是由Function构造的,f3这种写法就跟对象的创建写法一样。f1、f2最终也都像f3一样是有Function这个函数构造出来的
f1、f2、f3为函数对象,Function跟Object本身也是函数对象

Js中每个对象(null除外)都和另一个对象相关联,通过以下例子跟内存效果图来分析Function、Object、Prototype、__proto__对象间的关系

function Animal(){}
var  anim = new Animal();
console.log(typeof Animal.prototype);    //object 
console.log(anim.__proto__===Animal.prototype);    //true
console.log(Animal.__proto__===Function.prototype);    //true
console.log(Animal.prototype.__proto__===Object.prototype);    //true
console.log(typeof Function.prototype);    //function
console.log(typeof Function.__proto__);    //function
console.log(typeof Function.prototype.prototype);   //undefined
console.log(typeof Function.prototype.__proto__);     //object
console.log(Function.prototype===Function.__proto__);   //true
console.log(typeof Object.prototype);    //object
console.log(typeof Object.__proto__);    //function
console.log(Object.prototype.prototype);    //undefied
console.log(Object.prototype.__proto__===null);    //null
console.log(Function.prototype===Object.__proto__);     //true
console.log(Function.__proto__===Object.__proto__);     //true
console.log(Function.prototype.__proto__===Object.prototype);     //true
var array = new Array();
var date = new Date();
console.log(array.__proto__===Array.prototype);     //true
console.log(Array.__proto__===Function.prototype);    //true
console.log(date.__proto__===Date.prototype);      //true
console.log(Date.__proto__===Function.prototype);      //true

通过上面代码可以得出:

所有对象包括函数对象的原型链最终都指向了Object.prototype,而object.prototype.__proto__===null,原型链至此结束。

Animal.prototype是一个普通对象。

Object是一个函数对象,也是Function构造的,Object.prototype是一个普通对象。

Object.prototype.__type__指向null。

Function.prototype是一个函数对象,前面说函数对象都有一个显示的prototype属性,但是Function.prototype却没有prototype属性,即Function.prototype.prototype===undefined,所有Function.prototype函数对象是一个特例,没有prototype属性

Object虽是Function构造的一个函数对象,但是Object.prototype没有指向Function.prototype,即Object.prototype!==Function.prototype

Prototype跟Constructor关系介绍

在 JavaScript 中,每个函数对象都有名为“prototype”的属性(上面提到过Function.prototype函数对象是个例外,没有prototype属性),用于引用原型对象。此原型对象又有名为“constructor”的属性,它反过来引用函数本身。这是一种循环引用(i.e. Animal.prototype.constructor===Animal)

constructor 属性是专门为 function 而设计的,它存在于每一个 function 的prototype 属性中。这个 constructor 保存了指向 function 的一个引用

console.log(anim.constructor===Animal);    //true
console.log(Animal===Animal.prototype.constructor);    //true
console.log(Animal.constructor===Function.prototype.constructor);   //true
console.log(Function.prototype.constructor===Function);    //true
console.log(Function.constructor===Function.prototype.constructor);    //true
console.log(Object.prototype.constructor===Object);    //true
console.log(Object.constructor===Function);    //true

注意:Object.constructor===Function;本身Object就是Function函数构造出来的

如何查找一个对象的constructor,就是在该对象的原型链上寻找碰到的第一个constructor属性所指向的对象

问题整理

  1. 为什么 xx.constructor.prototype 可以访问到当前对象的原型。

'str'.constructor.prototype

'str'.constructor 指向当前对象的构造函数

(构造函数).prototype:即函数的prototype 属性

1) 函数有prototype属性,所以可以访问到

2) 函数的prototype属性会在创建实例的时候作为实例的原型而存在。

所以 'str'.constructor.prototype 就可以访问到当前对象实例的原型。

'str'.constructor == String

true.constructor == Boolean

(1).constructor == Number

{}.constructor == Object

[].constructor == Array

function(){}.constructor == Function

result:全部都是:function Function(){}

推论:内置对象的构造器,全部都是 function Function(){},包括Function本身。所以js所有的内置对象的构造器都是 function Function(){}

2.

Number.__proto__ === Function.prototype // true

Boolean.__proto__ === Function.prototype // true

String.__proto__ === Function.prototype // true

Object.__proto__ === Function.prototype // true

Function.__proto__ === Function.prototype // true

Array.__proto__ === Function.prototype // true

RegExp.__proto__ === Function.prototype // true

Error.__proto__ === Function.prototype // true

Date.__proto__ === Function.prototype // true

Function.prototype.__proto__ == Object.prototype

Object.prototype.__proto__ == Object.prototype

Number.prototype.__proto__ == Object.prototype

Boolean.prototype.__proto__ == Object.prototype

String.prototype.__proto__ == Object.prototype

Array.prototype.__proto__ == Object.prototype

RegExp.prototype.__proto__ == Object.prototype

Error.prototype.__proto__ == Object.prototype

Date.prototype.__proto__ == Object.prototype

推论:只有函数才有 prototype属性,所以上面的 XXX.prototype 中的XXX都是构造函数,又有2中的 XXX.__proto__。所以:XXX既可以是内置对象,也可以是构造函数。根据情景判断。Object的所有实例的原型都是 Object.prototype

Object.constructor == Function

Function.prototype.__proto__ == Object.prototype;

并且:Object.prototype.__proto__ == null;

目录
相关文章
|
1月前
|
JavaScript 前端开发
如何在 JavaScript 中使用 __proto__ 实现对象的继承?
使用`__proto__`实现对象继承时需要注意原型链的完整性和属性方法的正确继承,避免出现意外的行为和错误。同时,在现代JavaScript中,也可以使用`class`和`extends`关键字来实现更简洁和直观的继承语法,但理解基于`__proto__`的继承方式对于深入理解JavaScript的面向对象编程和原型链机制仍然具有重要意义。
|
1月前
|
设计模式 JavaScript 前端开发
js中new和object.creat区别
【10月更文挑战第29天】`new` 关键字和 `Object.create()` 方法在创建对象的方式、原型链继承、属性初始化以及适用场景等方面都存在差异。在实际开发中,需要根据具体的需求和设计模式来选择合适的方法来创建对象。
|
2月前
|
JavaScript 前端开发
JavaScript - 测试 Prototype
JavaScript - 测试 Prototype
16 0
|
3月前
|
JavaScript 前端开发
一个js里可以有多少个async function,如何用最少的async function实现多个异步操作
在 JavaScript 中,可以通过多种方法实现多个异步操作并减少 `async` 函数的数量。
|
3月前
|
存储 JavaScript 前端开发
JS篇(Array、Object)
JS篇(Array、Object)
24 1
|
3月前
|
JavaScript 前端开发
JavaScript prototype(原型对象)
JavaScript prototype(原型对象)
36 0
|
3月前
|
JavaScript 前端开发
JavaScript基础知识-原型(prototype)
关于JavaScript基础知识中原型(prototype)概念的介绍。
43 1
|
4月前
|
JavaScript 前端开发 开发者
Vue.js 响应式变革来袭!结合热点技术,探索从 Object.defineProperty 到 Proxy 的奇妙之旅,触动你的心
【8月更文挑战第30天】在 Vue.js 中,响应式系统自动追踪并更新数据变化,极大提升了开发体验。早期通过 `Object.defineProperty` 实现,但存在对新旧属性处理及数组操作的局限。Vue 3.0 引入了 `Proxy`,克服了上述限制,提供了更强大的功能和更好的性能。实践中,可根据项目需求选择合适的技术方案,并优化数据操作,利用懒加载等方式提升性能。
48 0
|
4月前
|
SQL JavaScript 前端开发
【Azure 应用服务】Azure JS Function 异步方法中执行SQL查询后,Callback函数中日志无法输出问题
【Azure 应用服务】Azure JS Function 异步方法中执行SQL查询后,Callback函数中日志无法输出问题
|
6月前
|
JavaScript 前端开发
JavaScript函数是代码复用的关键。使用`function`创建函数
【6月更文挑战第22天】JavaScript函数是代码复用的关键。使用`function`创建函数,如`function sayHello() {...}`或`function addNumbers(num1, num2) {...}`。调用函数如`sayHello()`执行其代码,传递参数按值进行。函数可通过`return`返回值,无返回值默认为`undefined`。理解函数对于模块化编程至关重要。
44 4

热门文章

最新文章

下一篇
DataWorks