javascript是唯一一个被广泛使用的基于原型继承的语言。
在JavaScript中,万物皆对象。
我们创建一个Person 构造函数,使用new 来创建一个实例对象person。
为了解决构造函数的对象实例之间无法共享属性的缺点,JavaScript提供了prototype属性。prototype 就是“一个给类的对象添加方法的方法”,使用prototype属性,可以给类动态地添加方法,以便在JavaScript中实现”继承”的效果。
JavaScript中每个对象都有prototype 属性,它本身也是对象,JavaScript中对象的prototype 属性的解释是:返回对象类型原型的引用。
function Person() {} Person.prototype.name="张三"; var person1 = new Person(); var person2 = new Person(); console.log(person1.name); // 张三 console.log(person2.name); // 张三上例中,将name 属性放在prototype 中,两个实例person1 和 person2 都共享同一个属性。
对于构造函数来说,prototype 是作为构造函数的属性;对于对象实例来说,prototype 是对象实例的原型对象,所以prototype 既是属性又是对象。
什么是原型?
每一个JavaScript对象(除null、undefined外)在创建的时候就会与之关联另一个对象,这个对象就是我们说的原型,每一个对象都会从原型"继承"属性。每个对象(除null、undefined)都会在其内部初始化一个属性,就是__proto__,这个属性会指向对象的原型。
__proto__ 是不对外公开的,是个私有属性,但是Firefox和Chrome的引擎将其暴露出来成为一个公共属性,我们可以对外访问和设置。所以我们可以使用Object.getPrototypeOf(obj) 代替 __proto__。
function Person() {} var person = new Person(); console.log(person.__proto__ === Person.prototype); // trueconstructor 属性, 构造函数,始终指向创建当前对象的构造函数。
每个函数都有一个prototype 属性,而constructor 是prototype 的属性,即对象实例的属性, 而prototype 是函数的属性。
function Person() {} var person = new Person(); console.log(Person === Person.prototype.constructor); // true console.log(person.constructor === Person); // true说明: 当获取person.constructor 时, 其实person 中并没有constructor 属性, 当不能读取到constructor 属性时,会从person 的原型也就是Person.prototype 中读取,正好原型中有该属性。所以person.constructor === Person.prototype.constructor 。
__proto__、prototype、cosntructor 之间的联系:
function Person() {} var person1 = new Person(); console.log(person1.__proto__ === Person.prototype); // true console.log(Person === Person.prototype.constructor); // true console.log(Object.getPrototypeOf(person1) === Person.prototype); // true当读取实例的属性时, 如果找不到,就会查找与对象关联的额原型中的属性,如果还查不到,就去原型的原型,一直找到最顶层位置。
function Person() {} Person.prototype.name = '张三'; var person = new Person(); person.name = '李四'; console.log(person.name); // 李四 delete person.name; console.log(person.name); // 张三这个例子中,我们设置了person 中的name 属性,所以我们读取到“李四”, 当我们删除了person 的name 属性时,读取person.name, 从person 中找不到就会从person 的原型也就是person.__proto__ === Person.prototype 中查找,哎,发现找到了name, 则输出”张三”。 如果没有找到呢?原型的原型又是什么?
使用最原始的方式创建:
var obj = new Object(); obj.name = '张三'; console.log(obj.name);所以原型对象是通过Object 构造函数生成的, 所以….
原型链并不是无限长,也有尽头—–null。
图中由相互关联的原型组成的链状结构就是原型链,也就是蓝色的路线。
继承意味着复制操作,然而JavaScript默认并不会复制对象的属性,相反,JavaScript只是在两个对象之间创建一个关联,这样,一个对象就可以通过委托访问另一个对象的属性和函数,所以与其叫继承,委托的说法反而更准确些。
