大家在使用vue的时候,肯定有想过为什么 data 要写成函数,而不允许写成对象?
首先我们要想到:
- data是 Vue 实例上的一个属性。
- 对象是对于内存地址的引用。
- 函数有自己的作用域空间。
vue 实例中的data是对象的写法,但是在组件中data是函数的写法,是因为写成函数,会有函数作用域的概念 ,是私有函数,只作用到当前组件中,不会影响到其它各个不同的组件。
第二点,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 中的值的一个副本,此后, 这两个变量可以参加任何操作而相互不受影响。具体位置如下示意图。
文章图片
引用类型赋值
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 指向堆内存中的同一个地址。其关系图如下示意图所示。
文章图片
至于第三点,大多数有 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 文件有多个子组件共同接收一个变量的话,改变其中一个子组件内此变量的值,会影响其他组件的这个变量的值。如果写成函数的话,那么他们有一个作用域的概念在里面,相互隔阂,不受影响。
推荐阅读
- JavaScript|vue 基于axios封装request接口请求——request.js文件
- 前端|web前端dya07--ES6高级语法的转化&render&vue与webpack&export
- 前端开发|Vue2.x API 学习
- vue|Vue面试常用详细总结
- vue|电商后台管理系统(vue+python|node.js)
- 腾讯TEG实习|腾讯实习——Vue解决跨域请求
- Vue|vue-router 详解
- vue|vue3替代vuex的框架piniajs实例教程
- Vue|Vue3.0的插槽是如何实现的()
- 前端|面试官(谈谈Vue和React的区别())