前端基础知识复习-JS(prototype)

prototype 软件界的标准翻译为‘原型’,代表事物的初始形态,也含有模型和样板的意义

JavaScript的所有function类型的对象都一个prototype属性,这个prototype属性本身又是一个object类型的对象,因此我们也可以给prototype对象添加任意的属性和方法。既然prototype是对象的‘原型’,那么由该函数构造出来的对象应该都会具有这个‘原型’的特性。事实上,在构造函数的prototype上定义的所有属性和方法,都是可以通过其构造的对象直接访问和调用的。也可以说,prototype提供了一群同类对象共享和方法的机制。

function person(name) { this.name = name }
person.prototype.sayhi = function() { console.log('my name is ' + this.name) }
var angel = new person('angel')
var apple = new person('apple')
angel.sayhi() // my name is angel
apple.sayhi() // my name is apple
apple.sayhi === angel.sayhi // true复制代码

// 多层次类型的构造函数
function person(name) { this.name = name } // 基类构造函数
person.prototype.sayhi = function() { console.log('my name is ' + this.name) }
function employee(name, salary) { // 子类构造函数
  person.call(this, name)
  this.salary = salary
}
employee.prototype = new person() // 建立一个基类的对象作为子类原型(原型继承)
employee.prototype.showMoney = function() { console.log(this.name + ' ¥' + this.salary) }
var angel = new person('angel') // 创建基类的angel对象
var pink = new employee('pink', 1314)
angel.sayhi() // my name is angel
pink.sayhi() // my name is pink
pink.showMoney() // pink ¥1314
pink.sayhi === angel.sayhi // true复制代码

在以上的代码里有一句: employee.prototype = new person() ,构造了一个基类的对象,并将其设为子类构造函数的prototype,这是很有意思滴,这样做的目的是为了后面,通过子类对象也可以调用基类proototype的方法,为什么可以这样呢???

看以下原型示意图(从别的地方截的^-^):


原来在Javascript中,prototype不但能让自己的资源共享,而且还有寻根问祖的天性,从而使得先辈们的资产可以代代相传。当从一个对象那里读取属性或调用方法时,如果该对象自身不存在,就会去自己关联的prototype对象那里找;如果prototype没有,又会去prototype自己关联的前辈prototype那里找,直到找到或追溯过程结束为止。

在Javascript内部,对象的属性和方法追溯机制是通过所谓的prototype链来实现的。当用new操作符构造对象时,也会同时将构造函数的prototype对象指派给新创建的对象,成为该对象内置的原型对象。对象内置的原型对象应该是对外不可见的,尽管有些浏览器(如firefox)可以让我们访问到这个内置原型对象,但并不建议这样做。内置的原型对象本身也是对象,也有自己关联的原型对象,这样就形成了所谓的原型链。

在原型链的最末端,就是Object构造函数prototype属性指向的那一个原型对象。这个原型对象是所有对象的最老祖宗,这个老祖宗实现了诸如toString等所有对象天生就该具有的方法。其他内置构造函数,如Function,Boolean,String,Date,RegExp等的prototype都是从这个老祖宗传承下来的,但他们各自又定义了自身的属性和方法,从而他们的子孙就表现出各自宗族的那些特征。

其实这就是‘继承’,是JavaScript特有的‘原型继承’。

‘原型继承’是慈祥又严厉的,允许孩子按照自己的爱好发展,但又不能动原型对象既有的财产,因为那可能会影响其他孩子。

function father(name) { this.name = name } // 基类构造函数
father.prototype.sayhi = function() { console.log('my name is ' + this.name) }

var childOne = new father('childOne')
var childTwo = new father('childTwo')
childTwo.sayhi = function() { console.log('hahaha, my name is' + this.name) }
var childThree = new father('childThree')

childOne.sayhi() // my name is childOne  childTwo的修改不会影响其他child
childTwo.sayhi() // hahaha, my name ischildTwo  childTwo按其自身创建的新方法输出
childThree.sayhi() // my name is childThree

childTwo.sayhi === childOne.sayhi // false
childThree === childOne // true复制代码

对象可以掩盖原型对象的那些属性和方法,一个构造函数原型对象也可以掩盖上层构造函数原型对象的属性和方法。这种掩盖其实只是在自己身上创建了新的属性和方法,只不过这些属性和方法与原型对象的同名而已。

我们随时可以给原型对象动态添加新的属性和方法:

function father(name) { this.name = name } // 基类构造函数
father.prototype.sayhi = function() { console.log('my name is ' + this.name) }
var childOne = new father('childOne')
childOne.sayhi() // my name is childOne  

father.prototype.saybye = function() { console.log('bye bye ' + this.name) } 
childOne.saybye() // bye bye childOne复制代码

同理,Javascript内置的如Object等的prototype上添加新的方法和属性,也是可以生效的,但一半不会这样做,因为这样会影响到所有对象。



转载于:https://juejin.im/post/5c0f8e46e51d451dac07794b

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值