原型和原型链简单理解

来源:互联网 发布:软件试运行报告 编辑:程序博客网 时间:2024/06/06 19:08

原型

每个函数function都有一个prototype属性,对于实例对象而言,构造函数的prototype即为实例的原型。

每个对象object都有一个__proto__,通常用__proto__属性表示原型链。


obj这个对象本质上是被Object函数创建的,因此obj.__proto__=== Object.prototype。我们可以用一个图来表示。

这里写图片描述

即,每个对象都有一个__proto__属性,指向创建该对象的函数的prototype。

那么上图中的“Object prototype”也是一个对象,它的__proto__指向哪里?

好问题!

在说明“Object prototype”之前,先说一下自定义函数的prototype。自定义函数的prototype本质上就是和 var obj = {} 是一样的,都是被Object创建,所以它的__proto__指向的就是Object.prototype。

但是Object.prototype确实一个特例——它的__proto__指向的是null,切记切记!

还有——函数也是一种对象,函数也有__proto__吗?

又一个好问题!——当然有。

函数也不是从石头缝里蹦出来的,函数也是被创建出来的。谁创建了函数呢?——Function——注意这个大写的“F”。

且看如下代码。

function fn(x,y){    return x+y;}console(fn(10,20));var f1 = new Function("x","y","return x+y");console.log(f1(5,6));

以上代码中,第一种方式是比较传统的函数创建方式,第二种是用new Functoin创建。

首先根本不推荐用第二种方式。

这里只是向大家演示,函数是被Function创建的。

好了,根据上面说的一句话——对象的__proto__指向的是创建它的函数的prototype,就会出现:Object.__proto__ === Function.prototype。用一个图来表示。

上图中,很明显的标出了:自定义函数Foo.__proto__指向Function.prototype,Object.__proto__指向Function.prototype,唉,怎么还有一个……Function.__proto__指向Function.prototype?这不成了循环引用了?

对!是一个环形结构。

其实稍微想一下就明白了。Function也是一个函数,函数是一种对象,也有__proto__属性。既然是函数,那么它一定是被Function创建。所以——Function是被自身创建的。所以它的__proto__指向了自身的Prototype。

篇幅不少了,估计也都看烦了。快结束了。

最后一个问题:Function.prototype指向的对象,它的__proto__是不是也指向Object.prototype?

答案是肯定的。因为Function.prototype指向的对象也是一个普通的被Object创建的对象,所以也遵循基本的规则。


判断JS数据类型的三种方法

1.typeof

console.log(typeof(x));    // undefinedconsole.log(typeof(10));   // numberconsole.log(typeof('abc')); // stringconsole.log(typeof(true));  // booleanconsole.log(typeof(function () { }));  //functionconsole.log(typeof([1, 'a', true]));  //objectconsole.log(typeof ({ a: 10, b: 20 }));  //objectconsole.log(typeof (null));  //objectconsole.log(typeof (new Number(10)));  //object

2.instanceof

function Foo(){}var f1 = new Foo();console.log(f1 instanceof Foo);  // trueconsole.log(f1 instanceof Object);  // trueconsole.log(Object instanceof Function);  // trueconsole.log(Function instanceof Object);  // trueconsole.log(Function instanceof Function);  // true

Instanceof的判断队则是:沿着A的__proto__这条线来找,同时沿着B的prototype这条线来找,如果两条线能找到同一个引用,即同一个对象,那么就返回true。如果找到终点还未重合,则返回false。

instanceof表示的是继承的关系,或者说是原型链的结构。

3.Object.prototype.toString
这种方法最准确,没有局限性。

Object.prototype.toString.call('') ;   // [object String]Object.prototype.toString.call(1) ;    // [object Number]Object.prototype.toString.call(true) ; // [object Boolean]Object.prototype.toString.call(undefined) ; // [object Undefined]Object.prototype.toString.call(null) ; // [object Null]Object.prototype.toString.call(new Function()) ; // [object Function]Object.prototype.toString.call(new Date()) ; // [object Date]Object.prototype.toString.call([]) ; // [object Array]Object.prototype.toString.call(new RegExp()) ; // [object RegExp]Object.prototype.toString.call(new Error()) ; // [object Error]Object.prototype.toString.call(document) ; // [object HTMLDocument]Object.prototype.toString.call(window) ; //[object global] window是全局对象global的引用

继承与原型链

javascript中的继承是通过原型链来体现的。先看几句代码

function Foo(){}var f1 = new Foo();f1.a=10;Foo.prototype.a=100;Foo.prototype.b=200;console.log(f1.a); //10console.log(f1.b); //200

以上代码中,f1是Foo函数new出来的对象,f1.a是f1对象的基本属性,f1.b是怎么来的呢?——从Foo.prototype得来,因为f1.__proto__指向的是Foo.prototype

访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着__proto__这条链向上找,这就是原型链。

看图说话:

上图中,访问f1.b时,f1的基本属性中没有b,于是沿着__proto__找到了Foo.prototype.b。


关于构造函数,继承,原型与原型链的理解,还可以参考阮一峰的博客:
1. Javascript继承机制的设计思想
2. Javascript 面向对象编程(一):封装
3. Javascript面向对象编程(二):构造函数的继承
4. Javascript面向对象编程(三):非构造函数的继承

这篇文章详细的写出了几种继承的方式,除了有个细节不到位,在子类通过sub.prototype=super.prototype之后还要记得修改sub的constructor哦~sub.prototype.constructor=sub
JS实现继承的几种方式

0 0