显式原型与隐式原型
显式原型:prototype
隐式原型:__proto__
1. 每个函数function都有一个prototype,即显式原型(属性)
2. 每个实例对象都有一个__proto__,可称为隐式原型(属性)
3. 对象的隐式原型的值为其对应构造函数的显式原型的值
4. 总结:
* 对象的__proto__属性: 创建对象时自动添加的, 默认值为构造函数的prototype属性值
*Object.prototype的__proto__属性指向null。
区别:
作用:
在js中万物皆对象,方法(Function)是对象,方法的原型(Function.prototype)是对象,对象具有属性(__proto__)称为隐式原型,对象的隐式原型指向构造该对象的构造函数的显式原型。
- //定义构造函数
- function Fn() { // 内部语句: this.prototype = {}
- }
- // 1. 每个函数function都有一个prototype,即显式原型属性, 默认指向一个空的Object对象
- console.log(Fn.prototype)
- // 2. 每个实例对象都有一个__proto__,可称为隐式原型
- //创建实例对象
- var fn = new Fn() // 内部语句: this.__proto__ = Fn.prototype
- console.log(fn.__proto__)
- // 3. 对象的隐式原型的值为其对应构造函数的显式原型的值
- console.log(Fn.prototype===fn.__proto__) // true
- //给原型添加方法
- Fn.prototype.test = function () {
- console.log('test()')
- }
- //通过实例调用原型的方法
- fn.test()
- 构造函数的显示原型的隐式原型:
- 内建对象(built-in object):比如Array(),Array.prototype.__proto__指向什么?Array.prototype也是一个对象,对象就是由 Object() 这个构造函数创建的,因此Array.prototype.__proto__ === Object.prototype //true,或者也可以这么理解,所有的内建对象都是由Object()创建而来。
- 自定义对象
function Foo(){} var foo = new Foo() Foo.prototype.__proto__ === Object.prototype //true 理由同上
Foo.prototype===foo._proto_ //true
(1)
function Bar(){} //这时我们想让Foo继承Bar Foo.prototype = new Bar() Foo.prototype.__proto__ === Bar.prototype //true
//我们不想让Foo继承谁,但是我们要自己重新定义Foo.prototype
Foo.prototype = { a:10, b:-10 } //这种方式就是用了对象字面量的方式来创建一个对象,根据前文所述 Foo.prototype.__proto__ === Object.prototype
注: 以上两种情况都等于完全重写了Foo.prototype,所以Foo.prototype.constructor也跟着改变了,于是乎constructor这个属性和原来的构造函数Foo()也就切断了联系。
- 构造函数的隐式原型
既然是构造函数那么它就是Function()的实例,因此也就指向Function.prototype,比如 Object.__proto__ === Function.prototype
手绘原型链
原型链是什么
实现继承主要依赖原型链。
什么是原型对象。我们知道每个构造函数一旦创建都有prototype指针指向它的原型对象(构造函数.prototype)。而原型对象(构造函数.prototype)会默认生成一个constructor指针又指向构造函数。在创建实例时,实例有一个内部属性[[prototype]]指向该原型对象。原型对象内创建的所有方法会被所有实例共享。
原型是什么?
在JavaScript中原型是一个prototype对象,用于表示类型之间的关系。
什么是原型链。
JavaScript万物都是对象,对象和对象之间也有关系,并不是孤立存在的。对象之间的继承关系,在JavaScript中是通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条,专业术语称之为原型链。
原型链就是创建一个构造函数,它会默认生成一个prototype属性并指向原型对象。使用下一个构造函数的原型对象作为这个构造函数的实例。即 nextFuction.prototype = new thisFuction();
在下下一个构造函数的原型对象 = new nextFuction。这样下去就会构成一条实例与原型之间的链条,这就是原型链。
为什么要有原型链
构造函数的所有实例都可以访问构造函数原型中的方法和属性。
也就是把共有的东西统一存放到一个共享空间。这样可以避免相同函数重复声明,减少空间占用,节省内存。实现继承,子类继承父类的方法和变量;
原型上可以定义一些方法和变量;
以这个原型建立的对象,可以使用原型方法和变量,从而实现继承。