背景:最近没什么需求,快要闲出屁了,所以重温了一下js的原型,结果大有收获,且偶然看到Snandy大神的《JavaScript中__proto__与prototype的关系》

这篇文章,感觉真是受益匪浅,原文出处:http://www.cnblogs.com/snandy/archive/2012/09/01/2664134.html

****前戏结束,开始正题****

一.所有构造器/函数的__proto__都指向Function.prototype(Function.prototype是一个空函数)

如何验证这句话呢?最好的方式就是上代码:

//内置的构造器
console.log(Number.__proto__===Function.prototype); //true //自定义的函数
var func=function(){};
function Person(name){
this.name=name
}
console.log(func.__proto__===Function.prototype); //true
console.log(Person.__proto__===Function.prototype); //true

这是为什么呢?我们接着上代码

看到了吧,无论是内置的构造器,还是自定义的构造器或函数,他们都是函数,或者说是方法;方法的原型自然指向Function.prototype

二.__protype__更像是构造器指向构造器的原型的一个指针;而prototype是构造器的一个属性,并且是一个对象(纯属个人看法)

还是代码验证:

图1

图2

我们可以看到Number没有__proto__属性,所以它更像是一个代码不可见的指针;而Number有prototype这个属性。

三、所有对象的__proto__都指向其构造器的prototype(在没有手动覆盖构造器的prototype的情况下)

首先,我们先看一下js内置构造器生成的对象:

var obj = {name: 'jack'}
var arr = [1,2,3]
var reg = /hello/g
var date = new Date
var err = new Error('exception') console.log(obj.__proto__ === Object.prototype) // true
console.log(arr.__proto__ === Array.prototype) // true
console.log(reg.__proto__ === RegExp.prototype) // true
console.log(date.__proto__ === Date.prototype) // true
console.log(err.__proto__ === Error.prototype) // true

再看看自定义构造器生成的对象:

//这里定义了一个Person构造器
function Person(name) {
this.name = name
}
var p = new Person('jack')
console.log(p.__proto__ === Person.prototype) // true

由此可见,所有对象的__proto__都指向其构造器的prototype,但是这句话是什么意思呢?“在没有手动覆盖构造器的prototype的情况下”,说到这儿了,那我们就接着

往下看,通常我们将属性写在构造器中,将方法写在构造器的原型里面(将方法写在原型中通常有2种方式)

(1)动态的为构造器的原型添加方法

function Person(name) {
this.name = name
}
// 修改原型
Person.prototype.getName = function() {}
var p = new Person('jack')
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p.constructor.prototype) // true

(2)完全重写构造器的原型

function Person(name) {
this.name = name
}
// 重写原型
Person.prototype = {
getName: function() {}
}
var p = new Person('jack')
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p.constructor.prototype) // false

以第一种方式为构造器的原型动态增加方法时,原型的constructor属性始终指向该构造器;而方法二则完全重写了构造器的原型,导致对象实例访问constructor时,在构造

器中找不到,在原型中也找不到,最终追溯到了Object.prototype。如下图所示:

图1

图2

看到了吧,构造器的原型是可以重写的,重写后prototype已经不是原先的prototype了(你大妈已经不是你原先的大妈了,你大爷还是你大爷,哈哈O(∩_∩)O哈哈~),

导致原先指向构造器的constructor属性不见了,所以对象实例在访问constructor时,吧啦吧啦,我就不重复说了,前面已经说过了。

********注:上面代码中用到的__proto__目前在IE6/7/8/9中都不支持,IE9中可以使用Object.getPrototypeOf(ES5)获取对象的内部原型。********

var p = {}
var __proto__ = Object.getPrototypeOf(p)
console.log(__proto__ === Object.prototype) // true

四、个人精辟总结(其实是在js高级程序设计中看到的)

实例的__proto__总是指向其构造函数的prototype,__proto__是实例与构造函数的原型之间的关系,而不是实例与构造函数之间的关系

javascript中构造器(函数)的__proto__与prototype初探的更多相关文章

  1. Javascript中的原型链,__proto__和prototype等问题总结

    1.js中除了原始数据类型 都是对象. 包括函数也是对象,可能类似于C++函数对象把 应该是通过解释器 进行()操作符重载或其他操作, 用的时候把它当函数用就行 但是实际上本质是一个对象 原型也是一个 ...

  2. Javascript中Function,Object,Prototypes,__proto__等概念详解

    http://anykoro.sinaapp.com/2012/01/31/javascript%E4%B8%ADfunctionobjectprototypes__proto__%E7%AD%89% ...

  3. Javascript中的函数(三)

    一:概述 函数是进行模块化程序设计的基础,编写复杂的Ajax应用程序,必须对函数有更深入的了解.JavaScript中的函数不同于其他的语言,每个函数都是作为一个对象被维护和运行的.通过函数对象的性质 ...

  4. JavaScript中Function函数与Object对象的关系

    函数对象和其他内部对象的关系 除了函数对象,还有很多内部对象,比如:Object.Array.Date.RegExp.Math.Error.这些名称实际上表示一个 类型,可以通过new操作符返回一个对 ...

  5. JavaScript中的函数表达式

    在JavaScript中,函数是个非常重要的对象,函数通常有三种表现形式:函数声明,函数表达式和函数构造器创建的函数. 本文中主要看看函数表达式及其相关的知识点. 函数表达式 首先,看看函数表达式的表 ...

  6. 浅析 JavaScript 中的 函数 currying 柯里化

    原文:浅析 JavaScript 中的 函数 currying 柯里化 何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字 ...

  7. 谈谈javascript 中的函数问题

    聊聊javascript中的函数 本文可作为李刚<疯狂htmlcssjavas讲义>的学习笔记 先说一个题外话 前几天在知乎上流传着一个对联  上联是雷锋推到雷峰塔 nnd 这是什么对联? ...

  8. 浅析 JavaScript 中的 函数 uncurrying 反柯里化

    柯里化 柯里化又称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果. 因此柯里化的过程是 ...

  9. JavaScript中hasOwnProperty函数

      JavaScript中hasOwnProperty函数方法是返回一个布尔值,指出一个对象是否具有指定名称的属性. 使用方法: object.hasOwnProperty(proName) 其中参数 ...

随机推荐

  1. 微信小程序API登录凭证(code),获得的用户登录态拥有一定的时效性

    调用接口获取登录凭证(code)进而换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的 会话密钥(session_key).用户数据的加解密通讯需要依赖会话密钥完成. OBJECT参 ...

  2. Spring AOP面向切面编程详解

    前言 AOP即面向切面编程,是一种编程思想,OOP的延续.在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等等.在阅读本文前希望您已经对Spring有一定的了解 注:在能对代码进行添 ...

  3. centos6下的安装navicat premium

    centos6下的安装navicat premium CentOS6下做开发的时候,数据库客户端是一个必须要有的工具,因为经常要和数据库打交道.由于数据库的类型多样,有MySQL.Oracle.Pos ...

  4. java Web jsp嵌入代码的三种方式

    1,表达式标签  <%= 2+3%> 唯一有显示功能的标签 作用: 计算表达式的返回值 将表达式的返回值显示到网页中. 注意: 表达式中不能有分号 2,普通脚本标签  <% %> ...

  5. libevent源码深度剖析四

    libevent源码深度剖析四 ——libevent源代码文件组织 1 前言 详细分析源代码之前,如果能对其代码文件的基本结构有个大概的认识和分类,对于代码的分析将是大有裨益的.本节内容不多,我想并不 ...

  6. 434. Number of Segments in a String 字符串中的单词个数

    [抄题]: Count the number of segments in a string, where a segment is defined to be a contiguous sequen ...

  7. 面试题:JavaIO流分类详解与常用流用法实例

    Java流概念: Java把所有的有序数据都抽象成流模型,简化了输入输出,理解了流模型就理解了Java IO.可以把流想象成水流,里面的水滴有序的朝某一方向流动.水滴就是数据,且代表着最小的数据流动单 ...

  8. sencha警告:[WARN][Anonymous] [Ext.Loader] Synchronously loading 'Ext.field.Text'

    chrome开发者工具下提示: [WARN][Anonymous] [Ext.Loader] Synchronously loading 'Ext.field.Text'; consider addi ...

  9. Luogu 2868 [USACO07DEC]观光奶牛Sightseeing Cows

    01分数规划复习. 这东西有一个名字叫做最优比率环. 首先这个答案具有单调性,我们考虑如何检验. 设$\frac{\sum_{i = 1}^{n}F_i}{\sum_{i = 1}^{n}T_i} = ...

  10. HTTP防盗链与反防盗链

    HTTP防盗链 通过上一次,我没对HTTP请求不再那么陌生了.防盗链无非就是别人来请求自己网站的信息,用于其他网站,那么如果我们能识别请求是来自那个网站,如果是外网,那么就重定向等其他处理.但在web ...