Skip to content

Javascript

1.typeof能判断哪些类型?

识别所有的值类型

js
let a;      typeof s // 'undefined'
const str = 'abc';      typeof s // 'string'
const n = 100;          typeof s // 'number'
const m = true;             typeof s // 'boolean'
const s = Symbol('s');    typeof s // 'symbol'

识别函数

js
typeof console.log // 'function'
typeof function (){} // 'function'

判断是否是引用类型(不可再细分)

js
typeof null // 'object'
typeof ['a','b']    // 'object'
typeof { x: 100}    // 'object'

2.何时使用 === 何时使用 ==

3.值类型和引用类型的区别?

js
    // 值类型
    let a = 10;
    let b = a;
    a = 20;
    console.log(b) // 10

    // 引用类型
    let a = { age: 10 };
    let b = a;
    a.age = 21;
    console(b.age) // 21

    // 常见的值类型
    const a ;
    const s = 'abc';
    const n =  100;
    const b = true;
    const s = Symbol('s')

    // 常见的引用类型
    const obj = {}
    const arr = []
    const n = null
    function fn() {}

4.手写深拷贝

js
/**
 * 深拷贝
 * @param obj 深拷贝的对象
 */
function deepClone(obj={}) {
    if(typeof obj !== 'object' || obj == null) {
        return obj
    }
    // 初始化返回结果
    let result
    if (obj instanceof Array) {
        result = []
    } else {
        result = {}
    }
    
    for (let key in obj) {
        // 保证key不是原型的属性
        if(obj.hasOwnProperty(key)) {
            // 递归调用
            result[key] = deepClone(obj[key])
        }
    }
    // 返回结果
    return result
}

5.变量计算 - 类型转换

1.字符串拼接

js
const a = 100 + 10; // 110
const b = 100 + '10'; // '10010'
const c = true + '10'; // 'true10'

2.== 运算符

js
100 == '100' // true
0 == '' // true
0 == false // true
false == '' // true
null == undefined // true

除了 == null之外,其他一律用 ===, 例如

js
const obj = { x: 100 }
if (obj.a == null) {}
// 相当于
// if(obj.a === null || obj.a === undefined) { }

3.if语句和逻辑运算
if语句判断的就是truly变量和falsely变量
truly变量: !!a === true的变量
falsely变量: !!a === false的变量

js
// 以下是fasely变量。除此之外都是 truly 变量
!!0 === false
!!NaN === false
!!'' === false
!!null === false
!!undefined === falsed
!!false === false

console.log(10 && 0) // 0
console.log('' || 'abc')  // abc
console.log(!window.abc)  // true

6.原型和原型链

原型

js
// class本质上是函数,可见class是语法糖
typeof Student // "function"
typeof Person // "function"

// 基于原型的执行规则
// 先在自身属性和方法上寻找
// 如果找不到则自动去__proto__中寻找

如何准确判断一个变量是不是数组?

js
[] instanceof Array // Object
[] instanceof Object // Object
{} instanceof Array // Object

手写一个简易的jQuery,考虑插件和扩展性

js
class jQuery{
    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
    }
    
    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 this.each(elem => {
            elem.addEventListener(type,fn,false)
        })
    }
    
}

// 插件
jQuery.prototype.dialog = function (info) {
    alert(info)
}

// "造轮子"

class myJquery extends jQuery{

    constructor(selector) {
        super(selector);
    }
    
    // 扩展自己的方法
    addClass() {
        
    }
    
    style(data) {
        
    }
}

// const $p = new jQuery('p')
// $p.get(1)
// $p.each((elem) => {console.log(elem.nodeName)})
// $p.on('click',() => alert('clicked'))

7.作用域和闭包

知识点
三级作用域:全局作用域,函数作用域,块级作用域(ES6新增)
闭包的两种情况

js
// 函数作为返回值
function create() {
    let a = 100
    return function () {
        console.log(a)
    }
}

let fn= create()
let a = 200
fn()

// 函数作为参数
function print(fn) {
    let a = 200
    fn()
}
let a = 100
function fn() {
    console.log(a)
}
print(fn)
js
function create() {
    const a = 100
    return function () {
        console.log(a)
    }
}

const fn = create()
const a = 200
fn() // 100


function print(fn){
    const a = 200
    fn()
}

const a = 100
function fn() {
    console.log(a)
}

print(fn) // 100

// 闭包自由变量的查找,是在函数定义的地方,向上级作用域查找,不是在执行的地方!!!

this的不用应用场景,如何取值?
this取什么样的值,是在函数执行的时候决定的,不是在函数定义的时候决定的 手写bind函数

js
Function.prototype.bind1 = function () {
    // 将参数拆解为数组,arguments为一个列表
    const args = Array.prototype.slice.call(arguments)
    // 获取要绑定的this
    const t = args.shift()
    // 获取真实的this
    const self = this
    return function () {
        return self.apply(t,args)
    }
}

实际开发中闭包的应用场景,举例说明
闭包隐藏数据,只提供API

js
function createCache() {
    const data = {}
    return {
        set:function (key,val){
            data[key] = val
        },
        get: function (key) {
            return data[key]            
        }
    }
}

const c = createCache()
c.set('a',100)
console.log(c.get('a'))
js
let a
for (let i = 0; i < 10 ; i++) {
    a=document.createElement('a')
    a.innerHTML= i + '<br>'
    a.addEventListener('click',function(){
        e.preventDefault()
        alert(i)
    })
    document.body.appendChild(a)
}

8.同步和异步有什么不同?

JS是单线程语言,只能同时做一件事
基于js是单线程语言
异步不会阻塞代码
同步会阻塞代码执行

js
// 同步

console.log(100)
setTimeout(() => {
    console.log(200)
})
console.log(300)

// 异步
console.log(100)
alert(200)
console.log(300)

应用场景
网络请求,如ajax图片加载 定时任务,如setTimeout

9.async-await和promise有什么关系?

执行async函数,返回的是Promise对象
await相当于Promise的then 执行async返回的是一个promise对象