最新web前端面试高频考点——JavaScript 篇(一)(1),2024年最新下血本买的

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

示例 1:判断所有的值类型(基本数据类型)

    let a = 'hello'
    let b = 11
    let c = true
    let d
    let s = Symbol('hi')
    console.log(typeof a) // string
    console.log(typeof b) // number
    console.log(typeof c) // boolean
    console.log(typeof d) // undefined
    console.log(typeof s) // symbol

示例 2:能判断函数

    let x = console.log
    let y = function() {}
    console.log(typeof x) // function
    console.log(typeof y) // function

示例 3:能识别引用类型(不能再继续识别)

	console.log(typeof null) // object
    console.log(typeof ['hello']) // object
    console.log(typeof {age: 20}) // object

手撕深拷贝

普通写法:

    const obj1 = {
        age: 20,
        name: '张三',
        address: {
            city: '北京'
        },
        arr: ['x', 'y', 'z']
    }

    const obj2 = deepClone(obj1)
    obj2.address.city = '上海'
    obj2.arr[0] = 'a'
    console.log(obj1.address.city) // 北京
    console.log(obj1.arr[0]) // x


    // 深拷贝
    function deepClone(obj = {}) {
        if(typeof obj !== 'object' || obj == null) {
            // 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
    }

简写形式:

	// 深拷贝函数
	function deepClone(obj) {
	    // 1 判断是否是非引用类型或者null
	    if (typeof obj !== 'object' || obj == null) return obj
	    // 2 创建一个容器
	    let result = new obj.constructor()
	    // 3 拿到对象的keys,给容器赋值
	    Object.keys(obj).forEach(v => result[key] = deepClone(obj[key]))
	    // 4 返回容器
	    return result
	}

变量计算 - 类型转换

  • 字符串拼接
  • ==
  • if 语句
  • 逻辑运算

示例 1:字符串拼接

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

示例 2:==

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

示例 2 扩展:

除了 == null 之外,其他都用 ===

    const obj = {name: 'zhangsan'}
    
    if (obj.age == null) {}
    // 相当于:
    if (obj.age === null || obj.age === undefined) {}

示例 3:truly 变量和 falsely 变量

  • truly 变量:!!a == true 的变量
  • falsely 变量:!!a === false 的变量

以下是 falsely 变量,除此之外都是 truly 变量

    !!0 === false
    !!NaN === false
    !!'' === false
    !!null === false
    !!undefined == false
    !!false === false

示例 4:逻辑判断

注:10 是 truly 变量,继续往后判断返回第二个值

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

原型和原型链

class 类

  • constructor
  • 属性
  • 方法

示例:

    // 学生类
    class Student {
        constructor(name, number) {
            this.name = name
            this.number = number
        }
        sayHi() {
            console.log(`姓名 ${this.name}, 学号 ${this.number}`);
        }
    }
    
    // 通过类 new 对象/实例
    const xialu = new Student('夏洛', '2022')
    console.log(xialu.name) // 夏洛
    console.log(xialu.number) // 2022
    xialu.sayHi() // 姓名 夏洛, 学号 2022

继承

  • extends
  • super
  • 扩展或重写方法

示例:子类继承父类

    // 父类
    class People {
        constructor(name) {
            this.name = name
        }
        eat() {
            console.log(`${this.name} eat food`);
        }
    }

    // 子类
    class Student extends People {
        constructor(name, number) {
            super(name)
            this.number = number
        }
        sayHi() {
            console.log(`姓名 ${this.name} 学号 ${this.number}`);
        }
    }

    // 子类
    class Teacher extends People {
        constructor(name, major) {
            super(name)
            this.major = major
        }
        teach() {
            console.log(`${this.name} 教授 ${this.major}`)
        }

    }

    // 实例
    const xialuo = new Student('夏洛', '2022')
    console.log(xialuo.name) // 夏洛
    console.log(xialuo.number) // 2022
    xialuo.sayHi() // 姓名 夏洛, 学号 2022
    xialuo.eat() // 夏洛 eat food

    // 实例
    const wanglaoshi = new Teacher('王老师', '语文')
    console.log(wanglaoshi.name) // 王老师
    console.log(wanglaoshi.major) // 语文
    wanglaoshi.teach() // 王老师 教授 语文
    wanglaoshi.eat() // 王老师 eat food

JS原型(隐式原型和显式原型)

类型判断 instanceof
    console.log(xialuo instanceof Student) // true
    console.log(xialuo instanceof People) // true
    console.log(xialuo instanceof Object) // true

原型

class 实际上是 函数

    console.log(typeof Student) // 'function'
    console.log(typeof Teacher) // 'function'
    console.log(typeof People) // 'function'

隐式原型和显式原型
  • 隐式原型:__prop__
  • 显式原型:prototype

实例对象的隐式原型等于对应构造函数的显示原型

    console.log(xialuo.__proto__) // People {constructor: ƒ, sayHi: ƒ}
    console.log(Student.prototype) // People {constructor: ƒ, sayHi: ƒ}
    console.log(xialuo.__proto__ === Student.prototype) // true

出处:https://coding.imooc.com/lesson/400.html#mid=30288
在这里插入图片描述

原型关系
  • 每个 class 都有一个显式原型 prototype
  • 每个实例都有隐式原型 __proto__
  • 实例的 __proto__ 指向对应 class 的 prototype
基于原型的执行规则
  • 获取属性 xialuo.name 或执行方法 xialuo.sayHi 时
  • 先在自身属性和方法寻找
  • 如果找不到则自动去 __proto__ 中查找

原型链

instanceof 顺着隐式原型往上找,找到返回 true,找不到返回 false

出处:https://coding.imooc.com/lesson/400.html#mid=30289

在这里插入图片描述

hasOwnProperty

hasOwnProperty 会查找一个对象是否有某个属性,但是不会去查找它的原型链

    console.log(xialuo.hasOwnProperty('name')) // true
    console.log(xialuo.hasOwnProperty('eat')) // false

手写简易 jQuery

通过 class类 和 原型,手写 jQuery 部分功能

	<p>第一段文字</p>
    <p>第二段文字</p>
    <p>第三段文字</p>
	
	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
            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 this.each(elem => {
                elem.addEventListener(type, fn, false)
            })
        }
        // 扩展很多 DOM API
    }

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

    // “造轮子”
    class myJQuery extends jQuery {
        constructor(selector) {
            super(selector)
        }
        // 扩展自己的方法
        addClass(className) {

        }
        style(data) {
            
        }
    }

测试:

在这里插入图片描述

作用域和闭包

作用域

  • 全局作用域
  • 函数作用域
  • 块级作用域

全局作用域:如 window 对象、document 对象
函数作用域:只能在函数里面使用
块级作用域:在块内有效

示例:全局作用域

在任何地方都能获取到

    window.a = 'zhangsan'
    function fn() {
        console.log(window.a)
    }
    fn() // zhangsan

示例:函数作用域

里面的函数能读取到外面函数的变量

    function fn1() {
        let a = 'zhangsan'
        function fn2() {
            let b = 'lisi'
            console.log(a)
        }
        fn2()
    }
    fn1() // zhangsan

外面的函数不能读取里面函数的变量

    function fn1() {
        let a = 'zhangsan'
        console.log(b)
        function fn2() {
            let b = 'lisi'
        }
        fn2()
    }
    fn1() // 报错:b is not defined

示例:块级作用域

在块之外读取不到变量

    if (true) {
        let x = 100
    }
    console.log(x) // 报错:x is not defined

示例:创建 10 个 <a> 标签,点击的时候弹出来对应的序号

	let a
    for(let i = 0; i < 10; i++) {
        a = document.createElement('a')
        a.innerHTML = i + '<br>'
        a.addEventListener('click', function (e) {
            e.preventDefault()
            alert(i)
        })
        document.body.appendChild(a)
    }

在这里插入图片描述

自由变量

  • 一个变量在当前作用域没有定义,但被使用了
  • 向上级作用域,一层一层依次寻找,直至找到为止
  • 如果到全局作用域都没找到,则报错 xx is not defined

示例:不在当前作用域的就一层层往上找,a、b 都要往上层找

    let a = 1
    function fn1() {
        let b = 2
        function fn2() {
            let c = 3
            console.log(a + b + c)
        }
        fn2()
    }
    fn1() // 6

闭包

作用域应用的特殊情况,有两种表现:

  • 函数作为返回值被返回
  • 函数作为参数被传递

总结:所有自由变量的查找,是在函数定义的地方,向上级作用域查找,不是执行的地方

示例:函数作为返回值

    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

  • 作为普通函数:指向 window
  • 使用 call apply bind :传入什么绑定什么(call、apply、bind的区别
  • 作为对象方法被调用:指向当前对象本身,异步指向 window,箭头函数的异步指向上级作用域
  • 在 class 方法中调用:指向当前实例本身
  • 箭头函数:取上级作用域 this 的值

注:this 的取值是在函数执行的时候确定的,不是在函数定义的时候确定的

示例 1:普通函数、使用 call、apply、bind

    function fn1() {
        console.log(this)
    }
    fn1() // window

示例 2:call、apply、bind 指定指向

    function fn1() {
        console.log(this)
    }
    fn1() // window



![img](https://img-blog.csdnimg.cn/img_convert/507b48a5c077c3eefc9f0ad16a97ea43.png)
![img](https://img-blog.csdnimg.cn/img_convert/2ba7afb06f4ace90a2dc91ebbee877f3.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

,箭头函数的异步指向上级作用域
* 在 class 方法中调用:指向当前实例本身
* 箭头函数:取上级作用域 this 的值


注:**this 的取值是在函数执行的时候确定的,不是在函数定义的时候确定的**


示例 1:普通函数、使用 call、apply、bind



function fn1() {
    console.log(this)
}
fn1() // window

示例 2:call、apply、bind 指定指向



function fn1() {
    console.log(this)
}
fn1() // window

[外链图片转存中…(img-2NDfTzN0-1715813438411)]
[外链图片转存中…(img-tw93fVEb-1715813438411)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 23
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值