1.变量类型
- typeof 能判断哪些变量类型
- 所有值类型(number,boolean,string,undefined,symbol,BigInt)
- 识别Function
- 判断是否是引用类型(不可细分)
- 何时使用 === ?何时使用 == ?
- 除 == null 外其他都是用 ===
- == 是会进行隐式转换数据类型
- 值类型和引用类型的区别
- 传递方式不同:值类型是赋值传递,引用类型是引用地址传递
- 存储方式不同:值类型是存储在栈中,引用类型是存储在堆中,把引用地址存放在栈中 (注意:考虑性能问题-值类型内存占用小,引用类型内存占用大,CPU耗时)
- 手写深拷贝
- 注意值类型和引用类型的区别
- 注意对象和数组的区别
- 递归
function deepClone (obj) { if (obj typeof !== 'object' || obj == null) { // 判断是否是数组或对象,不是则返回 return obj } // 初始化返回值 let result; // 是数组还是对象 if (obj instanceof Array) { result = [] } else { reuslt = {} } // 遍历 for (let key in obj) { // 判断是否是原型的属性 if(obj.hasOwnPrototype(key)) { result[key] = deepClone(obj[key]) // 递归 } } return result; }
变量计算-类型转换
- 字符串拼接
1 + '100' = 1100 ==100 == '100' 0 == '' 0 == false '' == false undefined == null // 以上计算都为 true const obj = {} if (obj.x == null) {} // 相当于 if (obj.x == null || obj.x == undefined) {}- if语句和逻辑运算
// truly变量: !!a === true // falsely变量: !!a === false // 以下都是falsely变量,除此之外都是truly变量 !!0 === false !!null === false !!undefined === false !!'' === false !!NaN === false !!false === false
2.原型和原型链
- 如何准确判断一个变量是不是数组
lat a = []; a instanceof Array - 手写一个简易的jQuery,考虑插件和扩展性
class jQuery {
// constructor
constructor(selector) {
const result = document.querySelectorAll(selector); // 选择器
const length = result.length;
for(let i = 0; i < length; i++) {
this[i] = result[i];// 遍历元素
}
this.length = length;
this.selector = selector;
}
// 获取元素方法
get(index) {
return this[index];
}
// 遍历元素方法
each(fn) {
for(let i = 0; i < this.length; i++) {
const elem = this[i];
fn(elem);
}
}
on(type, fn) {
return each((elem) => {
elem.addEventLister(type, fn, false)
})
}
}
// 插件
jQuery.prototype.diago = function () {
alert('插件')
}
// 扩展‘造轮子’
class myjQuery extends jQuery {
constructor (selector) {
super(selector)
}
addClassName (className) {
return this.each(elm => {
elm.className = className
})
}
}
-
原型和原型链
-
原型
- 每个class都有显示原型
prototype - 每个实例都有隐式原型
__proto__ - 实例的
__proto__指向对应class的prototype
- 每个class都有显示原型
-
原型的执行规则
- 获取属性或执行方法时,先在自身属性和方法上寻找,如果找不到则自动去
__proto__中查找
- 获取属性或执行方法时,先在自身属性和方法上寻找,如果找不到则自动去
-
原型链
- 原型链就是基于原型的执行规则层层往上查找,直到找到
null,从而形成原型链。
- 原型链就是基于原型的执行规则层层往上查找,直到找到
-
3.作用域和闭包
- this的不同应用场景,如何取值?
this的指向不是定义的时候决定的,而是直执行的时候确定的
// 当做普通函数被调用 function foo () { console.log(this) } foo() // window foo.call({x: 1}) // {x: 1} var f1 = foo.bind({x: 2}) f1() // {x: 2} // 箭头函数: 当前函数调用 const student = { name: 'zhangsan' sayHi () { // this 即当前对象 console.log(this) }, wait () { setTimeout(function() { console.log(this) // this === window } }, waitAgain () { setTimeout(() => { console.log(this) // this 即当前对象 }) } } // apply \ call \ bind // 作为对象函数被调用 // 在class的方法中被调用 class Student { constructor(name) { this.name = name this.age = 20 } sayHi () { console.log(this) } } const zhangsan = new Student('zhangsan') console.log(zhangsan) // Student {name: 'zhangsan', age: 20} - 手写bind函数
Function.prototype.bind1 = function () {
// 拆解参数成数组
const arr = Array.prototype.slice.call(arguments)
// 截取第一个参数,即this指向
const t = arr.shift()
// 函数foo.bind()中的foo
const self = this
// 返回函数
return function () {
return self.apply(t, arr)
}
}
function foo (a, b, c) {
console.log(this, 'this is foo')
console.log(a, b, c)
}
var f1 = foo.bind1({x: 1}, 1, 2, 3)
var res = f1()
console.log(res)