【JS不正经学习】--vue常见的问题

2 篇文章 0 订阅

前言:
工作中我们通过百度和官方文档很容易就知道一个语法怎么使用,但是你知道其中的原理吗?为什么要用这种方式?下面我们看看一些前端同学面试vue中可能经常被问及的问题。

在这里插入图片描述

VUE常见的问题

问题1、vue的 data 为什么要写成函数,而不允许写成对象?


可能从你接触vue你就是这样写的,但你是不是从未思考过为什么data是通过函数返回一个对象,为什么不直接写一个对象呢?带着这个问题往下看。

想要理解这个问题,首先要知道以下三个知识点:

  • dataVue 实例上的一个属性。
  • js的数据类型(基本类型和引用类型)
  • 函数作用域
  1. 第一点无可厚非,data属性附着于 Vue 实例上
  2. 对于第二点js的数据类型,基本上大家都知道有基本类型和引用类型。

数据类型

基本数据类型: Number, String, Boolean, Null, Undefined, Symbol。简单的数据段,存放在内存中,占据固定大小的空间
引用数据类型: Object(除了基本类型皆为对), 保存在内存中, 引用类型的变量实际上保存的不是变量本身,而是指向该对象的指针。

栈(Stack) 和 堆(Heap)

学过数据结构的都知道被称为后入先出(LIFO,last-in-first-out)的数据结构。栈内存是内存中用于存放临时变量的一片内存块。当声明一个基本变量时,它就会被存储到栈内存中。
例如下面这段代码,他们在栈内存中存储的形式如下所示:

const a = 10;
const b = 20;
const c = a;

下图演示了这种基本数据类型赋值的过程:

栈内存

很显然,a, c两个变量占用了不同的存储空间,所以他们之间也并没有什么联系。
栈内存的地址分配是连续的,所以在后续也不能对其进行进一步的扩充或者删除。

堆内存的存储不同与栈,引用类型在栈内存中保存的实际上是对象在堆内存中的引用地址,过这个引用地址可以快速查找到保存中堆内存中的对象,变量其实是保存在栈内存中的一个指针,这个指针指向堆内存。

  var obj1 = {
    a: 1
  };
  var obj2 = {};
  var obj3 = obj1;
  obj3.b = 22;

  console.log(obj1); // {a:1, b: 22}

从上面我们可以得知,当我改变obj3中的数据时,obj1中数据也发生了变化;这就印证了我们前面说的,因为变量都是对象类型,属于引用类型,所以给obj3 赋值的只是栈中的地址,而不是真正保存在堆里的对象,当修改 obj3 的时候,会根据地址返回到堆内存中进行修改,因为他们的引用地址指向同一对象,因此我们只修改了obj3,obj1也同步改变。

下图展示引用类型如何保存在内存中:

heap

我们在访问引用类型时,需要在栈内存中查找 对应的地址,在去堆内存中取得真正的值,访问速度自然不及栈内存。

可以看出,我们对引用类型复制时,只是将地址复制了一遍,修改的时候回相互影响,所以对引用类型进行复制的时候,应该将堆内存中的值复制,然后将新地址赋值给变量。这就涉及到了 深拷贝.

  1. 第三点我们都知道js每个函数都有自己的作用域

解释完上面三点,我们就来解释问题1:为什么 data 要写成函数而不是对象?

data 为对象的示例代码:

  function MyCompnent() {};
  MyCompnent.prototype.data = { age: 12 };
  var Jack = new MyCompnent();
  var Tony = new MyCompnent();
  console.log(Jack.data.age === Tony.data.age); // true
  Jack.data.age = 13;
  console.log('Jack ' + Jack.data.age + '岁;' + 'Tony ' + Tony.data.age + '岁'); // Jack 13岁;Tony 13岁

data 为函数的示例代码:

  function MyCompnent() {
    this.data = this.data();
  };
  MyCompnent.prototype.data = function () {
    return {
      age: 12
    }
  };

  var Jack = new MyCompnent();
  var Tony = new MyCompnent();
  console.log(Jack.data.age === Tony.data.age); // true
  Jack.data = {age: 13};
  console.log('Jack ' + Jack.data.age + '岁;' + 'Tony ' + Tony.data.age + '岁'); // Jack 13岁; Tony 12岁

我们利用上面两段代码模拟了Vue实例上的data,我们创建一个构造函数 MyCompnent, 它相对于Vue,在其原型链上声明一个 data 属性,其实就相对 Vue.$data, 然后声明两个实例,我们发现当data为对象的时候,两个实例相互影响,为函数的时候,那么就互不会影响。

tips:

这是一个经常在面试中会被问到的问题,vue的data为什么是函数而不是对象,以及js数据类型相关的问题,通过这篇帖子希望能彻底弄懂。

小结

Vue 里面data属性之所以不能写成对象的格式,是因为对象是对地址的引用。如果一个.vue 文件有多个子组件共同接收一个变量的话,改变其中一个子组件内此变量的值,会影响其他组件的这个变量的值。如果写成函数的话,因为函数作用域的存在,相互隔阂,不受影响。

问题2: 待补充…

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

small_Axe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值