JS 中的原型对象 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
noahlam
V2EX    Javascript

JS 中的原型对象

  •  1
     
  •   noahlam 2018-04-18 09:51:19 +08:00 3088 次点击
    这是一个创建于 2738 天前的主题,其中的信息可能已经有所发展或是发生改变。

    JS 中的原型对象

    白天写了一篇 [ JS 中创建对象的方法] ,写完以后感觉意犹未尽(实际情况是感觉原型那块内容没有交 代清楚),所以开这一篇继续聊聊关于 Javascript 中的原型对象

    相信用过 vue 的童鞋,都经常这样做,用 Vue.prototype.xxx = xxx 把一个方法或者属性添加到 Vue 对象的原型上, 这样,我们在 vue 实例的任何地方,都可以用这个方法或属性了,我最喜欢用的,就是把异步请求库 (我比较喜欢用 axios )挂载到 vue 原型上:

    // 一般是./src/mian.js // 这里为了方便理解就直接引入 axios,实际使用,我们可以先用 axios 封装一个异步请求模块 // 在模块里做一些拦截或者处理,然后再导入这个模块。具体做法看 import axios from 'axios' import Vue from 'vue' import App from './App' // 为所有 Vue 实例添加一个 post 模块,可以在 vue 实例中直接使用 this.post Vue.prototype.post = axios new Vue({ el: '#app', components: { App }, template: '<App/>' }) 

    这了是 prototype 就是我们所说的原型,那什么是原型呢? 我们看看 MDN 给的解释

    当谈到继承时,Javascript 只有一种结构:对象。每个对象都有一个私有属性(称之为 [[Prototype]]), 它指向它的原型对象( prototype )。该 prototype 对象又具有一个自己的 prototype, 层层向上直到一个对象的原型为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。

    视乎看起好有点拗口,没关系,我用自己的话总结了一下

    1.prototype 其实就是存在于对象中的一个特殊的对象,你可以把它理解为对象的一个属性或方法, 如 a.prototype,看起来是不是很像对象 a 的一个属性呢?

    2.每个对象都有一个 prototype,除了 null

    那这个 prototype 是干嘛的呢? 其实回头看看上面关于 vue 的代码就知道了, prototype 最主要的作用就是该原型所属对象的所有实例,都能共享 prototype 里的属性和方法 上面的代码中,通过向 Vue.prototype 中添加一个 post 方法,然后就可以在所有 vue 实例中使用该方法,就是个简单的实践。

    我们回头看看 [ JS 中创建对象的方法] 里面的原型模式

    function Student(){} // 声明一个空函数 Student.prototype.name = 'xiaohong' Student.prototype.age = 17 Student.prototype.gender = 'f' Student.prototype.study = fucntion() { console.log('我在学习...')} 

    我们先定义了一个空函数,注意:这个时候,我们并没有认为的给函数添加一个 prototype 属性 /方法, 而 Student 却自动有了 prototype,然后我们往 prototype 里面添加了 name,age,gender 属性和 study 方法, 然后我们用 new 实例化 2 个 Student 对象出来

    var studentA = new Student() console.log(studentA.name) // xiaohong console.log(studentA.age) // 17 console.log(studentA.gender) // f studentA.study() // 我在学习... var studentB = new Student() console.log(studentB.age) // xiaohong console.log(studentB.name) // 17 console.log(studentB.gender) // f studentB.study() // 我在学习... 

    上面的例子可以看出,对象的 prototype 里面的属性和方法,在该对象的所有实例里面,都是共享的 那如果我们想要让实例对象有自己的属性 /方法,该怎么办呢? 比如,我想让 studentB 的名字是'lili', 很简单,直接在实例对象上添加该属性 /方法:

    studentA.name = 'lili' studentA.study = function () { console.log('我在偷懒') } console.log(studentA.name) // lili console.log(studentB.name) // xiaohong studentA.study() // 我在偷懒 studentB.study() // 我在学习... 

    可以看出,studentA 的属性 /方法被改变的时候,studentB 没有对应的跟着改变,这是为什么呢? 不是说好的全所有 prototype 里的属性 /方法都是共享的吗?事实上,prototype 里的属性 /方法,确实是共享的, 问题出在我们是在实例对象上赋值,所以这个属性 /方法,是属于实例的,而不是属于 prototype 的,prototype 的属性, 也无法在实例对象上写入,也就是说,实例对象和 prototype 上,同时存在了 name 属性和 study 方法,那么, 为什么 studentA 和 studentB 访问到的属性 /方法 会不一样呢? 其实每次访问一个属性 /方法的时候, 都会先从实例对象开始查找,如果实例上有,就直接返回,如果实例上没有,就继续往 prototype 上查找,有就返回, 如果 prototype 上还有 prototype,那么还会继续网上查找,直到原型链的最顶层。如果都没有查到,则会返回 undefined。

    那么新的问题来了,我们该如何判断一个属性,是属于实例本身的,还是属于 prototype 的? 答案是 hasOwnProperty 方法, hasOwnProperty 方法可以检测到实例对象里面有没有给定的属性,该方法只能检测到实例里面的属性,检测不到 prototype 上的

    studentA.hasOwnProperty('name') // true studentB.hasOwnProperty('name') // false 

    那如果想同时查找实例对象和原型对象 prototype 呢?我们可以用 in 操作符

    'name' in studentA // true 'name' in studentB // true 

    有了这 2 个方法,我们就可以组合起来判断属性是属于实例还是原型了。

    这里老是说到实例,不得不提一下,实例对象虽然是构造函数“构造”出来的,但是其实跟构造函数没有直接联系, 实例对象内部指向的是构造函数的 prototype (原型)。 实例跟构造函数的一个间接关系是 实例.prototype.constructor --> 构造函数

    关于原型的介绍就到这里,有需要更深入的童鞋,建议去读一下 Javascript 权威指南。里面关于原型的介绍比我这详细。

    下面列几个 Javascript 权威指南里面介绍的关于原型的方法

    1. 获取一个实例对象的原型 (ES5 才支持)

      Object.getPrototypeOf(studentA) // Student.prototype

      部分浏览器( chrome,safari,firefox )也支持一个属性 __proto__

      studentA.__proto__ == Student.prototype

    2. 判断一个构造函数是否是指定实例对象的原型

      Student.prototype.isPrototypeOf(studentA) // true

    好了,关于原型对象的话题,就到这里了,感谢收看!

    如果觉得对您有用,请给本文的github加个 star,万分感谢,另外,github 上还有其他一些关于前端的教程和组件,有兴趣的童鞋可以看看,你们的支持就是我最大的动力。

    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5250 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 05:46 PVG 13:46 LAX 22:46 JFK 01:46
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86