你的位置:首页 > Java教程

[Java教程]js原型链和vue构造函数

javascript - vue和数组原型链的问题。 - SegmentFault 思否

vue和数组原型链的问题。javascript 数组 vue.js 1.1k 次浏览 问题对人有帮助,内容完整,我也想知道答案 0 问题没有实际价值,缺少关键内容,没有改进余地 ...

JS原型和原型链 - 追梦的老头 - 博客园

alert(cat.sex);//undefine 也就是说明实例只能继承构造函数原型上的属性和方法...5. JS原型和原型链 6. JS字符串截取 7. vue 监听路由变化 8. vue wa...

JS原型链-原型、构造函数、实例和原型链、instanceof -..._CSDN博客

标签: JS原型链 instanceof 个人分类: JS 构造函数: 可以new的函数是构造函数...Vue不同构建版本解释 Vue基础(手写总结版) npm全局安装没有权限解...

Vue.js入门【2-2】恶补JavaScript中的对象原型链 - CSDN博客

Js中的对象、构造函数、原型、原型链及继承 tanzhengyu 03-14 3181 1、对象...Vue.js进阶【5-0】vue-router入门 Vue.js入门【2-0】恶补JavaScript...

js基础篇——原型与原型链的详细理解 - chua1989 - 博客园

我们还知道函数对象的原型对象的构造函数就是函数对象...拿当前vue的项目来说,端返回的就是简单的html...1. js基础篇——原型与原型链的详细理解(35895) ...

人人都能懂的Vue源码系列—02—Vue构造函数 - 一个前端菜鸟的成长...

Vue.prototype._init 在core/instance/init.js中我们找到了_init的定义。代码已经...下篇博文主要介绍resolveConstructorOptions相关的内容,涉及到原...

JS原型链简单图解 - 最骚的就是你 - 博客园

JS中原型链,说简单也简单。 首先明确: 函数(Function...或者说是函数类型实例的构造函数(constructor);与之...2. Re:vue axios全攻略 你这全复制粘贴...

一篇文章理解JS继承——原型链/构造函数/组合/原型式/寄生式/寄生...

可以用寄生组合继承实现ES6 Class extends,但是还是会有细微的差别 参考文章: [1]《js继承、构造函数继承、原型链继承、组合继承、组合继承优化、寄生...

关于Android工程师转vue的三两事儿(10)--原型与原型链_慕课手记

说起原型和原型链接,着实让我这个前端菜鸟胡搞了好...交配生出一大堆小狗出来,其中交配就被称为构造函数...Vue.js 0人推荐 若觉得本文不错,就分享一...

一张图看懂 JS 原型链 - s_qiu - 博客园

JS 原型链,画了张图,终于理清楚各种关系有木有 分类: JavaScript « 上一篇...vue(3) 捕获(1) 操作系统版本检测(1) 钩子函数(1) 浏览器版本检测(1) 冒...

完整原型链详细图解(构造函数、原型、实例化对象) - sp..._CSDN博客

Js中的对象、构造函数、原型、原型链及继承 03-14 3225 1、对象在传统的面向...Vue.js 1篇 WebStorm 2篇 Redux 1篇 Mobx 1篇 Ionic 9篇 Cordov...

instanceof的使用: 对象与构造函数在原型链上是否有关..._CSDN博客

// instanceof : 对象与构造函数在原型链上是否有关系 function Aaa() { } var a1 = new Aaa(); alert( a1 instanceof Aaa ); // true 查询...

原型链与构造函数 - liuyongshun2的博客 - CSDN博客

构造函数、实例、原型、原型链之间的关系 07-08 145 1、构造函数是什么 所谓...js正则匹配原理 git 在工作中实际应用 vue工作中使用情况 vue组件...

JavaScript作用域、闭包、对象与原型链概念及用法实例总结_ ...

可以将JS的对象分为三类:用户创建对象,构造函数对象,原型对象。 所有对象中都有...据彭博报道, 英国区块链机构Juniper Research警告说,加 最新文章 vue中引用swiper...

什么是JavaScript原型链和this的值? - 何海宝的博客

本文分为js的原型链和this的指向 2个部分。 一、...this 是你call 一个函数时传的 context,假如你从来...Vue webapp webpack windows wordpress zepto...

面试一个5年的前端,却连原型链也搞不清楚,满口都是Vue,React之类...

我拿着我实习半年的简历应聘,我的优势主要是vue前端工程化开发,当然我js基础不...五年不知道原型链,可以判断这个候选人是一个典型框架熟练工,如果我要...

vue is a constructor and should be called with the ..._百度知道

1个回答 - 回答时间: 2017年10月19日 - 2人觉得有用

vue is a constructor and should be called with VUE是一个构造函数,应该调用 重点词汇 vue= Vista User#39;s Exchange,Vista用户交换机 constructor构造器...更多关于js原型链和vue构造函数的问题gt;gt;

js原型链是什么_localstorage_js原型和原型链面试题_js数据类型_...

首页/ js原型链是什么/ 列表 axure怎么预览和生成原型文件 有时候我们在使用axure的时候,想预览和生成原型文件,怎么操作呢,下面来分享一下方法打开默认浏览器之后,...

...angular_js原型和原型链_vue 钩子函数_vue使用教程 - 雪都美食网

vue scope,vue inarray,angular,vue.js 面试题,vue v-if,vue splice 不起作用,vue使用教程,vue foreachjs原型和原型链,vue 钩子函数

从一道题解读JS原型链 – 前端开发,JQUERY特效,全栈开发,vue开发

之前对js原型和原型链的理解一直觉得很绕,绕来绕去的,在看了《JavaScript高级...在默认情况下,所有的原型对象都会自动获得一个constructor(构造函数)...华南植物园街坊欢乐节什么时候?广州华南植物园街坊欢乐节时间?华南植物园中秋游园会活动时间?广州华南植物园中秋游园会有什么好玩的?广州街坊文化节在哪里开幕?广东街坊文化节来华南植物园吗?2017广东街坊文化节时间?街坊文化节活动地点?中秋节去华南植物园有什么活动?广州华南植物园优惠活动介绍?深圳锦绣中华中秋节有什么活动?锦绣中华中秋节门票多少钱?北京出发去法国旅游 北京出发去法国旅游 北京出发去法国旅游 北京出发去法国旅游 北京出发去法国旅游 北京出发去法国旅游 北京出发去法罗群岛旅游 北京出发去法罗群岛旅游 北京出发去法罗群岛旅游 北京出发去法罗群岛旅游 北京出发去法罗群岛旅游 北京出发去法罗群岛旅游 北京出发去法属波利尼西亚旅游 北京出发去法属波利尼西亚旅游 北京出发去法属波利尼西亚旅游 北京出发去法属波利尼西亚旅游 北京出发去法属波利尼西亚旅游 北京出发去法属波利尼西亚旅游 北京出发去法属圭亚那旅游 北京出发去法属圭亚那旅游 北京出发去法属圭亚那旅游 北京出发去法属圭亚那旅游 北京出发去法属圭亚那旅游 北京出发去法属圭亚那旅游

一、什么是原型链?

 

简单回顾下构造函数,原型和实例的关系:     每个构造函数(constructor)都有一个原型对象(prototype),原型对象都包含一个指向构造函数的指针,而实例(instance)都包含一个指向原型对象的内部指针. 然鹅,在js对象里有这么一个规则:  如果试图引用对象(实例instance)的某个属性,会首先在对象内部寻找该属性,直至找不到,然后才在该对象的原型(instance.prototype)里去找这个属性. 少废话,先来看个例子:  
 function Fun1 () {  this.win = "skt" } Fun1.prototype.getVal = function () {  return this.win } function Fun2 () {  this.other_win = "rng" } Fun2.prototype = new Fun1 () Fun2.prototype.getOtherVal = function () {  return this.other_win } let instance = new Fun2() console.log(instance.getVal()) //skt
在上述例子中,有一个很有意思的操作,我们让原型对象指向了另一个类型的实例,即: constructor1.property = instance2 那么他是怎么找到instance.getVal()的?这中间又发生了什么?   1).首先会在instance1内部属性中找一遍;  2).接着会在instance1.__proto__(constructor1.prototype)中找一遍,而constructor1.prototype 实际上是instance2, 也就是说在instance2中寻找该属性;  3).如果instance2中还是没有,此时程序不会灰心,它会继续在instance2.__proto__(constructor2.prototype)中寻找...直至Object的原型对象 
 搜索轨迹: instance1--> instance2 --> constructor2.prototype…-->Object.prototype

 

这种搜索的轨迹,形似一条长链, 又因prototype在这个游戏规则中充当链接的作用,于是我们把这种实例与原型的链条称作 原型链  二、prototype 和 __proto__ 都是个啥? 1.prototype是函数才有的属性
 let fun = function () {} console.log(fun.prototype) // object console.log(fun.__proto__) // function
2.__proto__是对象具有的属性,但__proto__不是一个规范的属性,对应的标准属性是 [[Prototype]]
 let obj = {} console.log(obj.prototype) // underfined console.log(obj.__proto__) // object
 我们可以把__proto__理解为构造器的原型,大多数情况下 __proto__ === constructor.prototype      ( Object.create()除外 )  三、new又是个什么鬼? 我们都知道new是一个实例化的过程,那么他是怎么实例化的?下面我们来看一个简单的例子: 
 function Fun() {  this.team = "rng" } let f = new Fun() console.log(f.team) // rng

上述代码中,我们通过new命令实例化了一个叫Fun的函数并赋值给f,这个新生成的实例对象f从构造函数Fun中得到了team属性,其实构造函数内部的this,就代表了新生成的实例对象,所以我们打印f.team的值就取到了rng这个值

这又是哪门子原理?答案如下?

  1. 创建一个空对象,作为将要返回的对象实例。
  2. 将这个空对象的原型,指向构造函数的prototype属性。
  3. 将这个空对象赋值给函数内部的this关键字。
  4. 开始执行构造函数内部的代码

也就是说,构造函数内部,this指的是一个新生成的空对象,所有针对this的操作,都会发生在这个空对象上。这也是为什么构造函数叫"构造函数"的原因,就是操作一个空对象(即this对象),将其“构造”为所需要的样子。

 

如果我不加new呢?

 function Fun() {  this.team = "rng" } let f = Fun() console.log(f) // undefined console.log(team) // rng

我们可以看出上面打印f为undefined,而team却有值,这又是为什么?

 

其实在这种情况下,构造函数就变成了普通的函数,而且不会被实例.而此时的this指向了全局,team就变成了全局变量,因此我们取到了值

 

四、 __proto__指向哪?

  说到__proto__的指向问题,还得取决于该对象创建时的实现方式.

 

  辣么,到底有那些实现方式?

1.字面量方式
 let obj = {} console.log(obj.__proto__) // object console.log(obj.__proto__ === obj.constructor.prototype) // true 证明用字面量创建的函数,他的__proto__ 等于 该对象构造器的原型

2.构造器方式

 function Func () {} let a = new Func() console.log(a.__proto__) // object console.log(a.__proto__ === a.constructor.prototype) // true 
3.Object.create()方式
 let obj1 = {name:"rng"} let obj2 = Object.create(obj1) console.log(obj2.__proto__) //{name: "rng"} console.log(obj2.__proto__ === obj2.constructor.prototype) // false

  注: Object.create(prototype, descriptors) 创建一个具有指定原型且可选择性地包含指定属性的对象

 

五、如何确定原型和实例的关系?

  想要确定原型和实例的关系,坦率的讲,有两种方式:  instance  和  isPrototype()  1.instanceof   我们用这个操作符来测试实例(instance)与原型链中出现过的构造函数,如果出现过则返回true,反之则为false   来来来,我们来测试一下:
 function Fun1 () {  this.laji = "uzi" } function Fun2 () {  this.strong = "faker" } Fun2.prototype = new Fun1() let fun2 = new Fun2 () console.log(fun2 instanceof Fun1) // true console.log(fun2 instanceof Fun2) // true console.log(fun2 instanceof Object) // true

由于原型链的关系,我们可以说fun2是一个对象Object,Fun1或是Fun2中任何一个类型的实例,所以这三个结果都返回了true

 2.isPrototype()   这个方法同样,只要是原型链中出现过的原型,该方法就会返回true,用法如下 
 console.log(Fun1.prototype.isPrototypeOf(fun2)) // true console.log(Fun2.prototype.isPrototypeOf(fun2)) // true console.log(Object.prototype.isPrototypeOf(fun2))// true

 

六、原型链的问题

 

  什么?原型链还有问题?买了佛冷,why?

  原因一: 当原型链中包含引用类型值的原型时,该引用类型值会被所有实例共享;

  原因二:在创建子类型时,不能向超类型的构造函数中传递参数.

 

七、如何解决原型链问题?

 

 

1.借用构造函数,也叫经典继承   基本思想: 在子类型构造函数的内部调用超类型构造函数   函数只是在特定环境中执行的代码的对象,因此通过使用 apply() 和 call() 方法也可以在(将来)新创建的对象上执行构造函数 看例子:

 

 function Father () {  this.team = ["letme","mlxg"] } function Son () {  Father.call(this) } let son = new Son() son.team.push("uzi") console.log(son.team)  //  ["letme", "mlxg", "uzi"] let little_son = new Son()  console.log(little_son.team) // ["letme", "mlxg"]
我们可以看出,借用构造函数一举解决了原型链的两大问题:  其一, 保证了原型链中引用类型值的独立,不再被所有实例共享;  其二, 子类型创建时也能够向父类型传递参数.但是还还还有一个问题,如果仅仅借用构造函数,那么将无法避免构造函数模式存在的问题:  方法都在构造函数中定义, 因此函数复用也就不可用了.而且超类型(如Father)中定义的方法,对子类型而言也是不可见的. so,借用构造函数的技术也很少单独使用. 2.组合继承

  组合继承, 有时候也叫做伪经典继承,指的是将原型链和借用构造函数的技术组合到一块,从而发挥两者优点的一种继承模式.

  基本思想: 使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承.

  这样,既通过在原型上定义方法实现了函数复用,又能保证每个实例都有它自己的属性. 接着看例子:
 function Father (team) {  this.team = team  this.people = ["mlxg","letme"] } Father.prototype.sayTeam = function () {  return console.log(this.team) } function Son (team,age) {  this.age = age  Father.call(this,team) } Son.prototype = new Father() Son.prototype.sayAge = function () {  return console.log(this.age) } let son = new Son("faker",8) son.people.push("uzi") console.log(son.people) // ["mlxg", "letme", "uzi"] son.sayAge()    //8 son.sayTeam()    // faker let little_son = new Son("bang",3) console.log(little_son.people) // ["mlxg", "letme"]  little_son.sayAge()    // 3 little_son.sayTeam()   // bang

  我们可以看出,组合继承既保证了引用类型不再被所有实例所共享,也能够让子类型创建时向父类型传参,同时,原型中的方法又能够被复用,可以说是避免了原型链中的两大问题以及借用构造函数的缺陷,因此他也是js中最常用的继承方式,而且

instanceof 和 isPrototypeOf( )也能用于识别基于组合继承创建的对象. 3.原型继承   基本思想: 借助原型可以基于已有的对象创建新对象, 同时还不必因此创建自定义类型   绳么意思?   比如我们在fun()函数内部, 先创建一个临时性的构造函数, 然后将传入的对象作为这个构造函数的原型,最后返回了这个临时类型的一个新实例.  
  function fun(o){   function F(){}   F.prototype = o;   return new F();  }
let obj = {arr:[11,22] fun(obj).arr.push(33) console.log(fun(obj).arr) // [11,22,33]
  在这个例子中,可以作为另一个对象基础的是obj对象,于是我们把它传入到fun()函数中,然后该函数就会返回一个新对象. 这个新对象将arr作为原型,因此它的原型中就包含引用类型值属性. 然后我们向该属性中又增加了一个元素,所以我们能够将它打印出来        *在原型继承中, 包含引用类型值的属性始终都会共享相应的值, 就像使用原型模式一样.4.寄生式继承   基本思想:创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真的是它做了所有工作一样返回对象
 function fun(o){  function F(){}  F.prototype = o;  return new F(); } let obj = {a:[11,22]} function createAnother(z) {  // 通过调用函数创建一个新对象  var clone = fun(z);  clone.sayHi = function () {   alert("hi");  }  return clone; }
    createAnother(obj)
 

  上面的例子中,我们把obj传入createAnother()函数中,返回的新对象clone不仅拥有了该属性,而且还被增强了,拥有了sayHi()方法;

 

  等一下,这里要注意: 使用寄生式继承来为对象添加函数, 会由于不能做到函数复用而降低效率;这一点与构造函数模式类似.

 

5.寄生组合式继承

  前面讲过,组合继承是 JavaScript 最常用的继承模式; 不过, 它也有自己的不足. 组合继承最大的问题就是无论什么情况下,都会调用两次父类构造函数: 一次是在创建子类型原型的时候, 另一次是在子类型构造函数内部. 寄生组合式继承就是为了降低调用父类构造函数的开销而诞生的   基本思想:不必为了指定子类型的原型而调用超类型的构造函数 
 function inheritPrototype(subType, superType) {  var protoType = Object.create(superType.prototype); //创建对象  protoType.constructor = subType;      //增强对象  subType.prototype = protoType;       //指定对象 } function Father(name) {  this.name = name;  this.colors = ["red", "blue", "green"]; } Father.prototype.sayName = function () {  console.log(this.name); } function Son(name, age) {  Father.call(this, name);  this.age = age; } inheritPrototype(Son, Father) Son.prototype.sayAge = function () {  console.log(this.age); } var instance = new Son("uzi", 3); instance.sayName(); //uzi instance.sayAge(); //3

   inheritPrototype函数接收两个参数:子类型构造函数和超类型构造函数。

    1. 创建超类型原型的副本。

    2. 为创建的副本添加constructor属性,弥补因重写原型而失去的默认的constructor属性

    3. 将新创建的对象(即副本)赋值给子类型的原型

  inheritPrototype的高效率体现在它没有调用superClass构造函数,因此避免了在subClass.prototype上面创建不必要多余的属性. 同时,原型链还能保持不变,可以说是相当奈斯

  由于寄生组合式继承,集寄生式继承和组合继承的优点于一身,是实现基于类型继承的最有效方法. 八.vue构造函数

我们在使用的vue的时候,经常会用new操作符去将他实例化,这说明vue也是一个构造函数,那么他是如何被创建的呢?我怀着无比激动的心情clone了vue的源码,仔细研究了一番vue源码地址我首先找到了src/core/instance/index.js文件,打开一看,惊了

在第八行代码中,创建了一个Vue的函数,这不就是Vue的构造函数么,而且在12行的警告中我更加肯定了,他说:Vue是一个构造函数,应该使用“new”关键字调用
然后他在下面,他分别在
  initMixin()  stateMixin()  eventsMixin()  lifecycleMixin()  renderMixin()
这五个方法中讲Vue作为形参传入,最后将Vue导出.
那么这五个方法是干什么的呢?我们先来看看initMixin()方法,打开./init.js文件,找到该方法
其他的代码我们先不管,我们就看该方法的前几行,他在Vue的原型中注入了_init方法,这个方法有点眼熟,我们好像在哪见过,对,就是刚才的index.js文件中

 

这个this_init(options)看上去像是一个内部初始化的一个方法,而option应该就是初始化时的一些配置项了,在Vue被实例化的时候,this._init()方法就会执行

 

接下来,我们来看一下./state.js文件,找到stateMixin方法