vue源码研究--Data为啥要写成函数()

大家在使用vue的时候,肯定有想过为什么 data 要写成函数,而不允许写成对象?
首先我们要想到:

  1. data是 Vue 实例上的一个属性。
  2. 对象是对于内存地址的引用。
  3. 函数有自己的作用域空间。
    vue 实例中的data是对象的写法,但是在组件中data是函数的写法,是因为写成函数,会有函数作用域的概念 ,是私有函数,只作用到当前组件中,不会影响到其它各个不同的组件。
第一点无可厚非,data属性附着于 Vue 实例上。
第二点,JS 的数据类型分为基本类型和引用类型,基本类型存储在栈内存中,引用类型存储在堆内存中,并且引用类型指向的是栈内存中的堆区地址。下面两个例子可以帮助你清晰地理解这句话。
基本数据类型赋值:
var a = 10; var b = 10; var c = a; console.log(a === b); // true a ++ ; console.log(a); // 11 console.log(c); // 10 a变化了 c没有变化

这段代码分别给 a、b 赋值 10,a 和 b 是全等的。然后用 a 来初始化 c,那么 c 的值也是 10。但 c 中的 10 与 a 中的是完全独立的,该值只是 a 中的值的一个副本,此后, 这两个变量可以参加任何操作而相互不受影响。具体位置如下示意图。
vue源码研究--Data为啥要写成函数()
文章图片

引用类型赋值
var a = {}; var b = {}; var c = a; console.log(a === b); // false a.name = 'Marry'; a.say = () => console.log('Hi Marry!'); console.log(c.name); // 'Marry' console.log(c.say()); // 'Hi Marry!'

上面这段代码。首先声明了a、b两个空对象,然后把 a 赋值给 c。因为对象是对栈内存的地址的引用,所以不同的对象的地址是不同的,所以他们不是全等的。接着给 a 新增加属性和方法,c 同样可以拥有此属性和方法,主要是因为 c 和 a 指向堆内存中的同一个地址。其关系图如下示意图所示。
vue源码研究--Data为啥要写成函数()
文章图片

至于第三点,大多数有 JS 基础的同学应该都能理解,每个函数都有自己的作用域。
以上是对三个注意点的说明,那么接下来我们就以两个例子解释问题一:为什么 data 要写成函数,而不允许写成对象?
data 为对象示例代码
function MyCompnent() {} MyCompnent.prototype.data = https://www.it610.com/article/{ age: 12 }; var JackMa = new MyCompnent(); var PonyMa = new MyCompnent(); console.log(JackMa.data.age === PonyMa.data.age); // true JackMa.data.age = 13; console.log('JackMa ' + JackMa.data.age + '岁;' + 'PonyMa ' + PonyMa.data.age + '岁'); // JackMa 13岁;PonyMa 13岁

上面的示例中,我们创建一个构造函数 MyCompnent,它充当的角色相当于 Vue,在他的原型属性上声明一个data属性,其实也相当于 Vue.$data。接着声明两个实例,改变其中一个实例,另外一个实例也会跟着改变,这个道理其实和引用类型赋值大同小异。
Tips:
关于构造函数的prototype继承原理,请参考详细解释:
面向对象的详细理解与继承方法对比
data 为函数的示例代码
function MyCompnent() { this.data = https://www.it610.com/article/this.data(); }MyCompnent.prototype.data = function() { return { age: 12 } }; var JackMa = new MyCompnent(); var PonyMa = new MyCompnent(); console.log(JackMa.data.age === PonyMa.data.age); // trueJackMa.data = {age: 13}; console.log('JackMa ' + JackMa.data.age + '岁;' + 'PonyMa ' + PonyMa.data.age + '岁'); // JackMa 13岁;PonyMa 12岁

上述代码模拟了 Vue 实例上的data为函数的时候,如果改变一个实例的data属性的值,那么不会影响到另外一个实例上的data的值。
【vue源码研究--Data为啥要写成函数()】Vue 里面data属性之所以不能写成对象的格式,是因为对象是对地址的引用,而不是独立存在的。如果一个.vue 文件有多个子组件共同接收一个变量的话,改变其中一个子组件内此变量的值,会影响其他组件的这个变量的值。如果写成函数的话,那么他们有一个作用域的概念在里面,相互隔阂,不受影响。

    推荐阅读