1. Vue2.0/3.0双向数据绑定的实现原理
https://developer.mozilla.org/zhcn/docs/web/javascript/reference/global_objects/object/defineproperty
- ES5:Object.defineProperty
- ES6:Proxy
<body>
姓名:<span id="spanName"></span><br>
<input type="text" id="inpName">
<script>
let obj = {name:''};
obj = new Proxy(obj,{
get(target,prop){ // target => obj prop => 传入的参数
return target[prop];
},
set(target,prop,value){
target[prop] = value;
observe();
}
});
function observe(){
spanName.innerHTML = obj.name;
}
inpName.oninput = function(){
obj.name = this.value
}
</script>
</body>
注意:react(MVC)、Vue(MVVM);MVC:单向数据改变,数据更改控制视图;MVVM:双向数据改变,数据<==>视图
2. 面试题(一)
var a = ?
if(a==1&&a==2&&a==3){
console.log(1);
}
- 方案一:
var a = {
i: 0,
toString(){ // 可换成valueOf 优先级更高
return ++this.i
}
}
- 方案二:
var a = [1,2,3]
a.toString = a.shift // 删除第一项
- 方案三:数据劫持实现
var i = 0;
Object.defineProperty(window,'a',{
get(){
return ++i;
}
})
3. 面试题(二)
// 面向对象 考察变量提升、new优先级、作用域等
function Foo(){
getName = function(){
console.log(1);
}
return this;
}
Foo.getName = function(){
console.log(2);
}
Foo.prototype.getName = function(){
console.log(3);
}
var getName = function(){
console.log(4);
}
function getName(){
console.log(5);
}
Foo.getName(); // 2
getName(); // 4
Foo().getName(); // 1
getName(); // 1
new Foo.getName(); // 2
new Foo().getName(); // 3
new new Foo().getName(); // 3
4. 深拷贝和浅拷贝
浅克隆:原始类型按值传递,对象类型按引用传递,与原对象共用一处内存,修改会使原对象也修改
深克隆:在内存中开辟一块新内存,将原对象中的所有值全部复制过去,与原对象完全脱离,修改新对象中的属性值不会影响原对象
let obj1 = {
a: 100,
b: [10,20,30],
c: {
x: 10
},
d: /^\d+$/
};
// 改变c.x的值两个对象的都会发生改变
let obj2 = {
...obj // 浅克隆 只克隆一层
};
5. 面试题(三)
let a = {},
b = '0',
c = 0;
a[b] = "wan"
a[c] = "dbq"
console.log(a[b]); // 输出dbq
// 对象的属性名不能重复,数字属性名==字符串属性名
let a = {},
b = Symbol('0'),
c = Symbol('0');
a[b] = "wan"
a[c] = "dbq"
console.log(a[b]); // 输出wan
// Symbol唯一值,此时 a = { Symbol('0'):"wan",Symbol('0'):"dbq"}
// 另外对象的属性名不一定是字符串,还有Symbol、null、Boolean、undefined等
6. 面试题(四)
var test = (function(i){
return function(){
alert(i *= 2); // 输出'4' alert会转化成字符串 控制台输出是4
}
})(2);
test(5);
注意:执行期上下文
i = 2 return AAAAAA
(内存地址) AAAAAA里面有alert(i*=2)
执行期上下文test(5)
,执行之后会被销毁,上面return那里不会销毁,形成闭包
7. 面试题(五)
var a = 0,
b = 0; // 以上两个是私有的a,b不会影响GO上的a,b
function A(a){
A = function(b){
alert(a + b++);
};
alert(a++);
}
A(1); // "1"
A(2); // "4"
GO
a = 0 b = 0
A = AAAAAA
堆 AAAAAA
"A" = function(b){
alert(a + b++);
};
alert(a++);
执行期上下文 A(1)
输出a=1,执行完毕后a=2,但此时的A = BBBBBB重写了全局方法的指向,导致闭包的形成
堆 BBBBBB
alert(a + b++);
执行期上下文 A(2)
a+b = 4
,然后输出4,接着b才变成5
8. let、const与var的区别
- 它们都是定义变量用的
- let、const不存在变量提升,不会预编译
- let、const在同一个作用域下不能重复定义相同的一个变量名称。var重复声明会重新赋值,let不会重复声明,会报错
- const声明一个只读的常量,一旦定义常量的值不能改变,const一定要初始化
- let、const有着严格的作用域(块级作用域)
- let、const有暂存性死区、window属性和方法