第八章 函数原型属性

8.1 原型链概要

prototype属性是JavaScript为每个Function()实例创建的一个对象。具体的说,他通过将new关键字创建的对象实例链接回创建它们的构造函数。因此,实例才可以分享或继承通用方法和属性。

var myArray = new Array('foo','bar');
console.log(myArray.join());

8.2 为什么要关注原型链

  1. 第一个原因是,原生构造函数(如Object(),Array(),Function()等,使用prototype属性,以便让构造函数实例继承属性和方法。这是JavaScript本身允许对象实例从构造函数的prototype属性继承属性和方法的机制。如果想更好地理解JavaScript,大家需要了解JavaScript本身是如何利用prototype对象的。
  2. 当创建用户自定义构造函数时(还没有实例化),可以像JavaScript原生对象那样使用继承。但首先必须了解它是如何工作的。
  3. 你可能确实不喜欢原型继承,或是更喜欢采用另一个模式的对象继承,但事实上,有一天你可能需要编辑或管理呢写认为原型继承非常优秀的人所编写的代码。这时,你应该了解原型继承是如何工作的,以及他如何被使用自定义构造函数的开发人员复制的。
  4. 通过使用原型继承,我们可以创建有效的对象实例,并且都是用相同的方法。如前所述,并非所有的数组对象(Array()构造函数的实例)都需要他们自己的join()方法。但所有实例都可以利用相同的join()方法。因为该方法在原型链中。

8.3 原型在所有function()实例上都是标准的

var myFunction = function(){};
console.log(myFunction.prototype);
console.log(typeof myFunction.prototype);

一定要完全理解的是:prototype属性来自Function()构造函数。只有我们打算将函数作为用户自定义构造函数(通过利用prototype属性)使用时额外(?????),但这不会改变这样的事实,Function()构造函数为每个实例赋一个prototype属性。

8.4 默认的prototype属性是Object()对象

所有关于原型的话题都会变得有点严肃。实际上,原型只是一个被称为“原型”的空对象属性,它是由JavaScript在后台创建,并且要通过调用哪个Function()构造函数来使用。

myFunction.prototype = {};
console.log(myFunction.prototype);

!prototype属性的值可以设置为JavaScript中任何可用的复杂性(即对象)。JavaScript将忽略任何设置为原始值的prototype属性。

8.5 将构造函数创建的实例连接至构造函数的prototype属性

Array.prototype.foo = 'foo';
var mySecondArray = new Array();
//仅在若干浏览器上可用
//console.log(mySecondArray._proto_.foo);
console.log(mySecondArray.constructor.prototype.foo);
console.log(mySecondArray.foo);

8.6 原型链的最后是Object.prototype

var myArray = [];
console.log(myArray.foo);

//因为在myArray.foo、myArray.prototype.foo、Object.foo中没有找到foo,所以foo是undefined

!注意,任何添加到Object.prototype的内容都将出现在for in 循环中。

8.7 原型链返回在链中找到的第一个匹配结果

Object.prototype.foo = 'Object-foo';
Array.prototype.foo = 'Array-foo';
console.log(myArray.foo);

8.8 用新对象替换prototype属性会删除默认构造函数属性

var Foo = function Foo(){};
Foo.prototype = {};
var FooInstance = new Foo();
console.log(FooInstance.constructor === Foo);//false,破坏了引用
console.log(FooInstance.constructor);//Object(),而非Foo()

var Bar = function Bar(){};
var BarInstance = new Bar();
console.log(BarInstance.constructor === Bar);//true
console.log(BarInstance.constructor);//true

8.9 继承原型属性的实例总能够获得最新值

实例总是能够从原型获得最新的值,不管何时被实例化、更改或附加(which?),在这种意义上,prototype属性是动态的。

var Foo = function Foo(){ };
var FooInstance = new Foo();
Foo.prototype = {x: 1};
console.log(FooInstance.x);//1
Foo.prototype.x = 2;
console.log(FooInstance.x);//2

8.10 用新对象替换prototype属性不会更新以前的实例

创建一个实例时,该实例将在实例化时被绑定之“刚完成的”原型。提供一个新对象作为prototype属性不会更新以创建历史和新原型之间的连接。(地址引用)

Foo.prototype = {x: 3};
console.log(FooInstance.x);//2
var FooInstance2 = new Foo();
console.log(FooInstance2.x);//3

这里的重点是,一旦开始创建实例,就不应用一个新对象来替换对象的原型,这样讲导致实例有一个指向不同原型的链接。(对原原型对象赋值呢???)

8.11 用户自定义构造函数向原生构造函数一样原型继承

console.log(new Date());
var Person = function(legs,arms){
    if(legs !== undefined) {this.legs = legs;}
    if(arms !== undefined) {this.arms = arms;}
};
Person.prototype.legs = 2;
Person.prototype.arms = 2;
Person.prototype.countLimbs = function(){return this.legs+this.arms;};

var chuck = new Person(0,0);
var chuck2 = new Person();
console.log(chuck.countLimbs());//0
console.log(chuck2.countLimbs());//4

8.12 创建继承链

设计原型继承的目的是要在传统面向对象编程语言中找到模仿继承模式的继承链。继承只是一个对象可以访问另外一个对象的属性。具体做法是,实例化想要继承的对象,将该对象实例作(new)为要继承该对象实例的函数的prototype属性值。完成之后,对象之间有一个链接,可以通过属性扩展为对象。

var Person = function(){this.far = 'far'};
Person.prototype.foo = 'foo';
var Chef = function(){this.goo = 'goo'};
Chef.prototype = new Person();
var cody = new Chef();
console.log(cody.far);
console.log(cody.foo);
console.log(cody.goo);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值