【面试题】Vue2为什么能通过this访问到data、methods的属性或方法_为什么vue的this可以拿到原型上的属性

            console.log(this.desc);
        }
    },
});
console.log(vm.name);
console.log(vm.sayName());

#### 二、Vue的构造函数


接收一个options参数


* 使用 instanceof 判断 this对象上是否出现了Vue的prototype,我们都知道this的指向是取决于谁调用
* this.\_init(options) 证明在这调用要么我们创建的实例上有\_init方法要么方法在Vue的prototype上,但是我们可以看到实例上并没有\_init方法 ,那么肯定在一个地方给Vue的prototype上加上了\_init方法 继续往下看



function Vue(options) {
if (!(this instanceof Vue)
) {
warn(‘Vue是一个构造函数,应使用“new”关键字调用’);
}
this._init(options);
}
//Vue() //错误的调用方式 进入警告判断 此时this指向window 然后window的 window.__proto__的指向的Window构造函数的prototype


#### 三 初始化initMixin(Vue)


在源码中会看到很多初始化的函数在这我们initMixin()


这个函数就是在Vue的原型上增加了\_init方法,方法接收一个参数,然后定义了vm变量,在我看的时候就想看看这个函数的this指向谁,其实也不难函数挂在Vue构造函数的原型上,调用还是在构造函数里面使用this调用,构造函数的this指向Vue实例,根据this的指向规则 此时的vm就指向了Vue构造函数的实例。


使用this的访问规则如果实例上没有就去原型上找


然后执行 initState(vm)



initMixin(Vue)
function initMixin(Vue) {
//prototype上增加init方法
Vue.prototype._init = function (options) {
var vm = this; //Vue实例
vm.age = 30
//代码进行了删减
initState(vm);
}
}
//这里只是举例测试
const vm = new Vue({})
console.log(vm.age) //30


#### 四 initState(vm)


这里就是对我们传入的data 或者methods进行不同的处理



//initState方法代码进行了删减
function initState(vm) {
vm._watchers = [];
var opts = vm.$options; //这里是我们在创建实例的时候传的参数
//如果传了methods 则去调用
if (opts.methods) { initMethods(vm, opts.methods); }
if (opts.data) {
initData(vm);
} else {
observe(vm._data = {}, true /* asRootData */);
}
}


#### 五 initMethods(vm, opts.methods)


如果有methods则取调用initMethods方法


前面主要是判断 methods中的值是不是函数,key有没有跟props冲突等


最后一段代码就是在vm的实例上增加方法vm[key]=methods[key],在读的时候我有这样一个以为为什么还要用bind改变this指向呢不本来就是写在vm实例上的方法吗 只能使用vm调用 那么方法的this不就指向vm吗?



/*
vm:构造函数实例
methods:我们传的methods对象
*/
function initMethods(vm, methods) {
var props = vm.$options.props;
//循环methods对象
for (var key in methods) {
{
//判断是否是函数 不是的化则作出警告
if (typeof methods[key] !== ‘function’) {
warn(
"Method “” + key + “” has type “” + (typeof methods[key]) + “” in the component definition. " +
“Did you reference the function correctly?”,
vm
);
}
//判断 methods 中的每一项是不是和 props 冲突了,如果是,警告。
if (props && hasOwn(props, key)) {
warn(
(“Method “” + key + “” has already been defined as a prop.”),
vm
);
}
//判断 methods 中的每一项是不是已经在 new Vue实例 vm 上存在,而且是方法名是保留的 _ $ (在JS中一般指内部变量标识)开头,如果是警告。
if ((key in vm) && isReserved(key)) {
warn(
"Method “” + key + “” conflicts with an existing Vue instance method. " +
“Avoid defining component methods that start with _ or $.”
);
}
}
//给实例增加methods中的方法 这样其实我们就已经可以用vm访问 到methods中的方法了
vm[key] = typeof methods[key] !== ‘function’ ? noop : bind(methods[key], vm);
}
}


问了群里大佬之后原来这步操作时为了防止用户改变this指向,专门做了个例子


在这我有定义了对象a里面有个age属性和fn,fn我赋值vm实例上的sayHi,然后a.fn()调用很明显this的指向已经被改变了,使用bind之后则不会



const vm = new Vue({
methods: {
sayHi() {
console.log(this.age, ‘hello-this’)
}
}
});
let a = {
age: 15,
fn: vm.sayHi
}
console.log(a.fn(), ‘vm’) //打印15


#### 六 initData(vm)


data是如何做到的使用this可以直接访问的,其实原理都一样,


首先在vm实例上增加了\_data,里面存的我们传入的data参数



function initData(vm) {
var data = vm.KaTeX parse error: Undefined control sequence: \n at position 279: …turn an object:\̲n̲' + …options.props;
var methods = vm.$options.methods;
var i = keys.length;
while (i–) {
var key = keys[i];
//判断key值有没有跟methods中的key重名
{
if (methods && hasOwn(methods, key)) {
warn(
(“Method “” + key + “” has already been defined as a data property.”),
vm
);
}
}
//判断key值有没有跟props中的key重名
if (props && hasOwn(props, key)) {

学习笔记

主要内容包括html,css,html5,css3,JavaScript,正则表达式,函数,BOM,DOM,jQuery,AJAX,vue等等

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

HTML/CSS

**HTML:**HTML基本结构,标签属性,事件属性,文本标签,多媒体标签,列表 / 表格 / 表单标签,其他语义化标签,网页结构,模块划分

**CSS:**CSS代码语法,CSS 放置位置,CSS的继承,选择器的种类/优先级,背景样式,字体样式,文本属性,基本样式,样式重置,盒模型样式,浮动float,定位position,浏览器默认样式

HTML5 /CSS3

**HTML5:**HTML5 的优势,HTML5 废弃元素,HTML5 新增元素,HTML5 表单相关元素和属性

**CSS3:**CSS3 新增选择器,CSS3 新增属性,新增变形动画属性,3D变形属性,CSS3 的过渡属性,CSS3 的动画属性,CSS3 新增多列属性,CSS3新增单位,弹性盒模型

JavaScript

**JavaScript:**JavaScript基础,JavaScript数据类型,算术运算,强制转换,赋值运算,关系运算,逻辑运算,三元运算,分支循环,switch,while,do-while,for,break,continue,数组,数组方法,二维数组,字符串

画属性,CSS3 新增多列属性,CSS3新增单位,弹性盒模型

[外链图片转存中…(img-fU7SERGT-1714173442548)]

JavaScript

**JavaScript:**JavaScript基础,JavaScript数据类型,算术运算,强制转换,赋值运算,关系运算,逻辑运算,三元运算,分支循环,switch,while,do-while,for,break,continue,数组,数组方法,二维数组,字符串

  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Vue2中,使用this来访问data中的属性,是因为Vue在实例化时对data对象中的每个属性进行了数据代理,将其转化为getter/setter。这样一来,当我们使用this来访问data中的属性时,实际上是在访问Vue实例的一个代理属性,而不是直接访问原始的data对象中的属性。 在getter函数中,Vue会返回原始的data对象中的属性值,而在setter函数中,Vue会将新的属性值保存到原始的data对象中。同时,Vue会通过响应式系统,检测到属性值的变化,并触发相关的更新操作,从而保证视图与数据的同步。 举个例子,如果我们有以下的Vue组件: ``` <template> <div>{{ message }}</div> </template> <script> export default { data() { return { message: 'Hello World' } } } </script> ``` 那么在实例化时,Vue会将message属性转化为getter/setter,代码类似于: ``` const vm = new Vue({ data: { message: 'Hello World' } }) Object.defineProperty(vm, 'message', { get() { return this._data.message }, set(newVal) { this._data.message = newVal } }) ``` 这样一来,当我们在模板中使用{{ message }}时,实际上是在调用Vue实例的message属性的getter函数,而当我们在代码中使用this.message = 'new message'时,实际上是在调用Vue实例的message属性的setter函数。由于Vue实例的message属性是一个代理属性,因此在属性值发生变化时,Vue会通过响应式系统检测到变化并更新相关的视图。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值