You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
functionFoo(name,github,blog){this.name=name;this.github=github;this.blog=blog;}Foo.prototype.aboutMe=function(){varinfo='my name is '+this.name+'. my github is '+this.github+'. my blog is '+this.blog;console.log(info);}varfoo=newFoo('htf','github.com/huangtengfei','huangtengfei.com');foo.aboutMe();// my name is htf. my github is github.com/huangtengfei. // my blog is huangtengfei.com
这是个典型的构建构造函数,然后创建对象的过程。那么,在 var foo = new Foo() 这一步发生了什么呢?
proto is the actual object that is used in the lookup chain to resolve methods, etc. prototype is the object that is used to build proto when you create an object with new.
prototype 与 proto 的联系与区别
重要的话放前面讲。首先,理解一个函数的原型属性
prototype
其实和实际的原型__proto__
没有关系至关重要。prototype
只有在 Function 中有,而__proto__
在 Function 和 Object 中都有。关于Function
在 JavaScript 中,除了五种原始类型(
Boolean
、Number
、String
、Null
、Underfined
),引用类型包括Array
、Object
、RegExp
、Function
、Date
、Error
等,但从根本上只有两种,即 Function 和 Object,其他的引用类型都是从 Object 衍生出来。对于这两种类型的判断,前者(原始类型)判断用
typeof
,后者(引用类型)用instanceof
。在 js 中,Function 和 Object 是平级的,而且 Function 能做但 Object 做不了的事情:
第一,Fuction 可以被执行。
第二,Fuction 可以被当做 Object 的构造函数。当使用 new 操作符后面跟着一个 Function 类型的变量时,这个 Function 变量会被当成构造函数返回一个 Object 对象。
第三,Function 有内置的
prototype
属性,而 Object 没有。正是因为有了把 Function 当做构造函数的功能,才需要 prototype 属性。关于继承(proto)
继承仅限于引用类型,即 Function 和 Object。JavaScript中的继承是基于原型链来实现的,用来明确继承关系的就是
__proto__
,毕竟只有它同时存在于两者。用最简单的话来描述javascript中继承的本质:一个对象A的
__proto__
属性所指向的那个对象B就是它的原型对象(或者叫上级对象、父对象),对象A可以使用对象B中定义的属性和方法,同时也可以使用对象B的原型对象C的属性与方法,以此递归,这也就是所谓的原型链。下面是一个对象继承的栗子。
prototype的作用
既然
__proto__
一个东西把继承问题就都解决了,那要prototype
做甚?并不,因为
__proto__
并非官方标准中定义的属性,当把一个Function当做构造函数使用时,继承关系需要借助prototype
实现。举个栗子:
这是个典型的构建构造函数,然后创建对象的过程。那么,在
var foo = new Foo()
这一步发生了什么呢?第一步,Foo 函数被执行。Foo 函数在 foo 的作用域下被执行,所以这里 this 指代的就是 foo,这样 name、github、blog 三个属性才会被当做 foo 的属性被创建。
第二步,将
foo.__proto__
指向Foo.prototype
。这才是 javascript 构造函数的精髓所在,之后的原理和 关于继承 部分的代码一样,foo 就继承了Foo.prototype
中(以及其原型链上)的属性与方法。对象的
__proto__
指向的是创建它的函数的prototype
,因此:结论
意思就是:
__proto__
是真正用来查找原型链去获取方法的对象。prototype
是在用new
创建对象时用来构建__proto__
的对象。更详细的区别可参考:prototype与__proto__的联系与区别
获取对象原型的方法
ECMA引入了标准对象原型访问器
Object.getPrototype(object)
,到目前为止只有 Firefox 和 Chrome 实现了此访问器。除了 IE,其他的浏览器支持非标准的访问器__proto__
,如果这两者都不起作用的,我们需要从对象的构造函数中找到的它原型属性。任何时候,
a.__proto__
和a.constructor.prototype
是等价的。constructor 与 prototype
图解可参考:js原型链原理看图说明 和 prototype原型
instance of 和原型的关系
如果 a 的原型属于 A 的原型链(即
a.__proto__ === A.prototype
),表达式a instance of A
值为 true。原型的作用
原型的作用当然是继承了。体现在以下两种情况:
一、当多个实例共用一个通用原型的时候,原型对象的属性一旦定义,就可以被多个引用它的实例所继承。栗子可以看 JavaScript 面向对象编程 一文
二、扩展原生构造函数 Function、String 等的功能,使其所有实例都拥有此扩展功能。
比如下面一个栗子,对字符串本身进行指定数目的复制:
参考
理解JavaScript原型
JavaScript探秘:强大的原型和原型链
The text was updated successfully, but these errors were encountered: