普通对象与函数对象
在javascript中万物皆对象,但对象是有区别的,分为普通对象和函数对象,那怎么区分呢,凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象,Object和Function都是JS自带的函数对象,都是通过new Function()创建的。看下面的例子:
function f1(){};
console.log(f1.prototype) //f1{}
console.log(typeof f1. prototype) //Object
console.log(typeof Function.prototype) // Function,这个特殊
console.log(typeof Object.prototype) //Object
console.log(typeof Function.prototype.prototype) //undefined
prototype和proto的概念
prototype是函数的一个属性(每个函数都有一个prototype属性),这个属性是一个指针,指向一个对象。它是显示对象的原型的属性。
__proto__是一个对象拥有的内置属性(请注意:prototype是函数的内置属性,__proto__是对象的内置属性),是JS内部使用寻找原型链的属性。
怎么理解呢?
简单点说,就是对象属性的修改和获取通过prototype来实现,而对象属性的继承通过__proto__来实现
new的过程
var Person = function(){};
var p = new Person();
new的过程拆分成以下三步:
(1) var p={}; // 初始化一个对象p
(2) p.\_\_proto\_\_ = Person.prototype;
(3) Person.call(p); // 构造p,也可以称之为初始化p
总结
1.原型和原型链是JS实现继承的一种模型。
2.原型链的形成是真正是靠__proto__ 而非prototype
要深入理解这两句话,我们举个例子:
var animal = function(){};
var dog = function(){};
animal.price = 2000;//
dog.prototype = animal;
var tidy = new dog();
console.log(dog.price) // undefined
console.log(tidy.price) // 2000为什么呢?
画一下内存图:
这说明什么问题呢,执行dog.price的时候,发现没有price这个属性,虽然prototype指向的animal有这个属性,但它并没有去沿着这个“链”去寻找。同样,执行tidy.price的时候,也没有这个属性,但是__proto__指向了animal,它会沿着这个链去寻找,animal中有price属性,所以tidy.price输出2000。由此得出,原型链的真正形成是靠的__proto__,而不是prototype。
因此,如果在这样指定dog.__proto__ = animal,那dog.price = 2000。