prototype是构造函数的一个属性,它决定了在构造出来的对象上__proto__属性将是什么样的。
如上图所示,理解JavaScript中的继承的关键是要理解母鸡如何产蛋的过程。
每个对象都可以有另一个对象作为其原型。然后前一个对象继承了它的所有原型属性。对象通过内部属性[[Prototype]]指定其原型。由[[Prototype]]属性连接的对象链称为原型链。
为了理解基于原型的继承是怎么样的,我们先来看一个例子。
var proto = {
describe: function () {
return 'name: '+this.name;
}
};
var obj = {
[[Prototype]]: proto,
name: 'obj'
};
> obj.describe
[Function]
> obj.describe()
'name: obj'
__proto__是Object.prototype对象的访问者属性。它暴露了访问它的对象的内部原型([[Prototype]])
function Foo(name) {
this.name = name
this.whoAmI = function () {
return this.name
}
}
var b = new Foo('b')
var a = new Foo('a')
b.say = function () {
console.log(`Hi from ${this.whoAmI()}`)
}
console.log(a.__proto__ === Foo.prototype); // true
console.log(a.__proto__ === b.__proto__); // true
JavaScript引擎在对象b上添加了一个say方法,而不是在Foo原型对象(Foo.prototype)上。 正如上图中看到的那样,a.__ proto__暴露了指向Foo.prototype对象的[[Prototype]]。同样,b.__ proto__也指向与a.__ proto__相同的对象。
除了通过指定模式创建对象之外,构造函数还可以执行另一个有用的操作 - 它会自动为新创建的对象设置原型对象。此原型对象存储在构造函数的原型对象属性中。
我们可以使用构造函数用b对象重写前面的例子。因此,对象a(原型)Foo.prototype的作用:
创建拥有原型对象属性x及方法calculate()的一个Foo对象。
function Foo(y) {
this.y = y;
}
Foo.prototype.x = 10;
Foo.prototype.calculate = function (z) {
return this.x + this.y + z;
};
使用对象Foo创建一个b对象实例。
var b = new Foo(20);
b.calculate(30); // 60
console.log(
b.__proto__ === Foo.prototype, // true
b.__proto__.calculate === Foo.prototype.calculate // true
b.__proto__.calculate === b.calculate, // true
Foo === b.constructor, // true
Foo === Foo.prototype.constructor, // true
);
正如上面打印出来的信息,对象b从Foo()继承了方法calculate。“Foo.prototype”自动创建一个特殊属性“constructor”,它是对构造函数本身的引用。实例b可以通过代理来找到它,并用来检测其构造函数。
这也是通过构造函数来创建对象,但是在这一系列的对象和实例之间我们的焦点是放在原型链上。原型对象其实也是普通的对象,也有属于它们自己的属性。如果原型具有对其原型的非空引用,依此类推,则称为原型链。
以下是JavaScript经典继承的图表。构造函数Foo只是虚构类的类名。 foo对象是Foo的一个实例。
现在我们可以从图中看到为什么当我们从Dog类继承Animal 时,我们会这样做:
function Dog() {} // the usual constructor function
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
当通过new操作符创建一个实例的时候,都发生了些什么:
注意Foo.prototype的原型(prototype)并不是来自原型链。
原型继承缺点:1、不能由子对象像父对象传递参数,2、对于引用型的属性修改之后会印象其他的实例对象;构造函数继承缺点:1、不能继承父对象原型上的方法 2、每次实例化对象会重新构建函数,浪费内存。
学过java的同学应该都知道,继承是java的重要特点之一,许多面向对象的语言都支持两种继承方式:接口继承和实现继承,接口继承只继承方法签名,而实现继承则继承实际的方法,在js中,由于函数没有签名,因此支持实现继承,而实现继承主要是依靠原型链来实现的,那么,什么是原型链呢?
在面向对象语言都会存在继承的概念,在面向对象语言中,继承的特点:继承了父类的属性和方法。那么我们现在主要研究css,css就是在设置属性的。不会牵扯到方法的层面。
1. 原型链继承;2,构造函数继承(对象冒充继承);3,组合继承(原型链继承+构造函数继承);4,原型式继承;5. 寄生组合式继承,为了解决引用共享和超类型无法传参的问题,我们采用一种叫借用构造函数的技术
JavaScript常用继承方式主要分为(7种):原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承、寄生组合继承以及继承多个对象。原型链继承(核心:将父类的实例作为子类的原型
继承到底是什么?继承(英语:inheritance)是面向对象软件技术当中的一个概念。如果一个类别B“继承自”另一个类别A,就把这个B称为“A的子类”,而把A称为“B的父类别”也可以称“A是B的超类”。继承可以使得子类具有父类别的各种属性和方法
当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。如果让原型对象指向另一个类型的实例.....有趣的事情便发生了.
构造函数,就是专门用来生成实例对象的函数。一个构造函数,可以生成多个实例对象,这些实例对象都有相同的结构。为了与普通函数区别,构造函数名字的第一个字母通常大写。
JavaScript对象继承的方法有很多,这里总结一下几种比较常用的方法。使用call/apply和Object.create()第一种方法使用call或apply方法,改变了 this 的指向而实现继承,将父对象的构造函数绑定在子对象上,即在子对象构造函数中加一行
要搞懂JS继承,我们首先要理解原型链:每一个实例对象都有一个__proto__属性(隐式原型),在js内部用来查找原型链;每一个构造函数都有prototype属性(显示原型),用来显示修改对象的原型
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!