三个基本概念:构造函数、原型、实例
每一个构造函数都有一个原型对象(prototype),原型对象都包含一个指向构造函数的指针(constructor),而实例都包含一个指向原型的内部指针(__proto__)。
emp1:
function Foo(y){ this.y = y ; } Foo.prototype.x = 10; Foo.prototype.calculate = function(z){ return this.x+this.y+z; }; var b = new Foo(20); alert(b.calculate(30));
所有函数的默认原型都是Object的实例,因此默认原型内部都有一个指针,指向Object.prototype,这也正是所有自定义对象都会继承toString()、valueOf()等方法的根本原因。
Foo的构造函数时Function 任何一个对象的__proto__都有值,因为每一个对象都有构造函数。
如图:
函数与对象
函数是对象,对象又都是通过函数创建的。任何一个函数内都有prototype属性。
在javascript中,一个对象就是任何无序键值对的集合,如果它不是一个主数据类型(undefined,null,boolean,number,or string),那它就是一个对象。
false明明是一个主数据类型,false.__proto__也会返回一个值 。因为在代码执行它会被强制转化成一个对象(Boolean 基本包装类型)。
原型写法
分步写法:(具有实时性)
function a (){ this.age = 1; } a.prototype.str = 'ss'; var b = new a(); a.prototype.name='tom'; console.log(b.str);//ss console.log(b.name); //tom
字面量写法:(会导致原型重写)
function a(){ this.name = 'w'; } a.prototype.str = 's'; var b = new a(); console.log(b.str); //s //字面量写法 a.prototype = { x:1 }; //a原型重写并没有反映到a之前创建 的实例中 console.log(b.str); //s console.log(b.x);//undefined //a的原型反映到重写后创建的实例中 var c = new a(); a.prototype.q = 3; console.log(c.x); //1 console.log(c.q); //3 console.log(c.str); //undefined
原型链 继承
函数a的原型为函数b的实例,函数a的实例就会继承a和b的原型的所有方法和属性。 见图《JavaScript高级程序设计》p163
new
__proto__
本质上其实是标准里规定的[[prototype]]
属性,原本是不可用 js 访问的,后来(据说标准里又规定可以)firefox 和 chrome 中把这个属性命名为__proto__
。后来ES
又添加了函数getPrototypeof
,这样就可以通过这个函数来访问这个属性,所以这个__proto__
现在不是标准的一部分。
然后,再说new
的创建过程,当执行new func()
的时候,执行过程如下
<script type="text/javascript"> var animal = function(){}; var dog = function(){}; animal.price = 2000; dog.__proto__ = animal; var tidy = new dog(); console.log(dog.price) //2000 console.log(tidy.price) // undefined </script>
constructor
constructor指的就是对象的构造函数 对象是由函数构造的
function Foo(){}; var foo = new Foo(); alert(foo.constructor);//Foo alert(Foo.constructor);//Function alert(Object.constructor);//Function alert(Function.constructor);//Function
因为Foo,Object,Function都是函数对象,又因为所有的函数对象都是Function这个函数对象构造出来,所以它们的constructor为Function
prototype与constructor的关系
function Dog(){}
(Dog === Dog.prototype.constructor);//true
console.log(Dog.prototype.hasOwnProperty('constructor'));//true
function Animal(){}
function Person(){}
var person = new Person();
console.log(person.constructor); //Person
任何一个函数的原型都有constructor属性
person是Person的实例,所以person继承Person原型上的所有属性和方法,Preson原型有constructor属性并指向Preson,所以person有constructor属性并指向Preson
深入一点
function Animal(){} function Person(){} Person.prototype = new Animal(); //prototype被重写了,没有constructor属性了
var person = new Person(); alert(person.constructor); //Animal
如图
图中的虚线表示Person默认的prototype指向(只作参考的作用)。但是我们将Person.prototype指向了new Animal。
还有