1、 clientX: clientX 事件属性返回当事件被触发时鼠标指针向对于浏览器页面(或客户区)的水平坐标。客户区指的是当前窗口。但是不包含窗口滑动条的滑动距离,包含margin的宽度。
2、call,apply, bind的区别
-
- call()、apply()、bind() 都是用来重定义 this 的指向,指向()中的对象
-
- bind 返回的是一个新的函数,你必须调用它才会被执行,call, apply则立即执行
-
- 传参的格式不一样,call(db, 参数1, 参数2...), apply(db, [参数1,参数2...]), bind(db, 参数1, 参数2...),call和bind若传数组作为参数,则整个数组会被认为是一个参数,apply传列表参数则报错
var obj={
name: 'xiaozhan',
age: 17,
myFun: function(f, t) {
console.log(this.name + '年龄'+this.age,'来自' + f + '去往' + t)
}
}
obj.myFun.call({name: 'xiaoli', age:18}, ['上海', '北京']) // xiaoli年龄18 来自上海,北京去往undefined
obj.myFun.bind({name: 'xiaoli', age:18}, ['上海', '北京'])() // xiaoli年龄18 来自上海,北京去往undefined
// obj.myFun.apply({name: 'xiaoli', age:18}, '上海', '北京') // 报错
3、箭头函数
- 箭头函数没有 this,所以需要通过查找作用域链来确定 this 的值。代码示例
- 因为箭头函数没有 this,所以也不能用 call()、apply()、bind() 这些方法改变 this 的指向
var value = 1;
var result = (() => this.value).bind({value: 2})();
console.log(result); // 1
var adder = {
base : 1,
add : function(a) {
var f = v => v + this.base; // this.base === 1
return f(a);
},
addThruCall: function(a) {
var f = v => v + this.base;
// this.base === 1
// 因为箭头函数没有this,call,apply不能改箭头函数this的指向,所以this还是原来的对象adder
// 所以这里this.base === 1
var b = {
base : 2
};
return f.call(b, a);
},
addThruCall2: function(a) {
function f(v){
return v += this.base; // 普通函数谁调用函数 this就指向谁 call 将this指向了b
}
var b = {
base : 2
};
return f.call(b, a);
}
};
console.log(adder.add(1)); // 输出 2
console.log(adder.addThruCall(1)); // 仍然输出 2(而不是3)
console.log(adder.addThruCall2(1)); // 输出 3
-
没有 arguments, 但是可以访问外围函数的arguments
function constant() { return () => arguments[0] } var result = constant(1); console.log(result()); // 1那如果我们就是要访问箭头函数的参数呢? 你可以通过命名参数或者 rest 参数的形式访问参数:
let nums = (...nums) => nums; -
不能通过 new 关键字调用
-
没有原型
4、vue中watch和change事件有什么相同和不同
- change可以传入参数,watch只能监听到特定属性变化
- watch可以获取nv,ov;change只能获取nv
5、vue中watch和computed有什么区别
- computed 计算属性 : 依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值。
- watch 侦听器 : 更多的是「观察」的作用,无缓存性,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作。
6、 从浏览器输入url到页面显示经历了哪些?
7、 Object.assign
- 语法
Object.assign(target,params1,params2) - 方法实行的是浅拷贝
const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);
obj1.a.b = 2;
obj2.a.b // 2
- 同名属性的替换
const target = { a: { b: 'c', d: 'e' } }
const source = { a: { b: 'hello' } }
Object.assign(target, source)
// { a: { b: 'hello' } }
-
数组的处理
Object.assign可以用来处理数组,但是会把数组视为对象
Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3] 替代下标0,1的值
-
取值函数的处理
Object.assign只能进行值的复制,如果要复制的值是一个取值函数,那么将求值后再复制。
const source = {
get foo() { return 1 }
};
const target = {};
Object.assign(target, source)
// { foo: 1 }
- 处理字符串
Object.assign({},'abc')
// {0: "a", 1: "b", 2: "c"}
- 数值和布尔值都会被忽略
8、 Set和Map结构
- Set
Set本身是一个构造函数,用来生成 Set 数据结构.它类似于数组,但是成员的值都是唯一的,没有重复的值。
const s = new Set();
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));
for (let i of s) {
console.log(i);
}
// 2 3 5 4
- 数组去重
// 去除数组的重复成员
[...new Set([1,2,1,3,4])]
// [1, 2, 3, 4]
- Map
为了解决object只能用字符串作为键的问题,ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false
注意,只有对同一个对象的引用,Map 结构才将其视为同一个键。这一点要非常小心。
const map = new Map();
map.set(['a'], 555);
map.get(['a']) // undefined
上面代码的set和get方法,表面是针对同一个键,但实际上这是两个不同的数组实例,内存地址是不一样的,因此get方法无法读取该键,返回undefined。
9、扩展运算符
扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
-
复制数组(浅拷贝)
const a1 = [1, 2]; // 写法一 const a2 = [...a1]; // 写法二 const [...a2] = a1; -
合并数组
const arr1 = ['a', 'b']; const arr2 = ['c']; const arr3 = ['d', 'e']; // ES5 的合并数组 arr1.concat(arr2, arr3); // [ 'a', 'b', 'c', 'd', 'e' ] // ES6 的合并数组 [...arr1, ...arr2, ...arr3] // [ 'a', 'b', 'c', 'd', 'e' ] -
与解构赋值结合
const [first, ...rest] = [1, 2, 3, 4, 5]; first // 1 rest // [2, 3, 4, 5]如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。
-
字符串
[...'hello'] // [ "h", "e", "l", "l", "o" ]
10、for for...in for...of
* for循环,遍历数组 i值可以改变
* for...in 循环 i值不能改变
* for...of循环值
11 、工作中遇到的问题
- Q:使用vue-router的addRoutes做权限管理,发现addRoutes后在this.$router.options.routes中获取不到动态添加的routes,无法显示菜单
分析原因:因为vue-router的设计是静态路由,虽然提供了addRoutes api,但是并没有添加到 this.$router.options.routes。
解决方案: 1、推荐: 维护一个vuex routes的数组,添加后放进去
2、不推荐: this.$router.options.routes.push(newRoutes) 改变了原有的设计,存在未知风险
- Q:使用html2canvas生成图片,对于有滚动条的数据,生成的图片只有可视区域的数据,导致显示不完整
分析原因:html2canvas根据body中显示的元素生成图片,获取不到table中overflow为sroll的隐藏元素
解决方案:目前解决方案:去除table中的滚动条,使table的父级出现滚动条,这样就可以获取到整个table,感觉方案不怎么完美,探索其他方案中...
- Q:v-for 如果使用index作为key,在数组变化时,当有checkbox勾选且第一项勾选第二项没有勾选时, 删除第一项数据后,第一项的checkbox勾选状态不对
分析原因:vue中的vdom是根据key复用的,若key相同,则当前节点被复用
解决方案:key 使用数据的唯一id,不实用index作为key