A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

var 和 let const 的区别
typeof 返回哪些类型
列举强制类型转换和隐式类型转换
手写深度比较,模拟 lodash isEqual
split() 和 join() 的区别
数组的 pop push unshift shift 分别做什么
数组 slice 和 splice 的区别
[10,20,30].map(parseInt) 返回的结果是什么?
ajax 请求 get 和 post 的区别?
call() apply() bind() 作用和区别
事件代理(委托)是什么?
闭包是什么?有什么特性?有什么负面影响?
如何阻止事件冒泡和默认行为?
查找,添加,删除,移动DOM节点的方法
如何减少DOM操作?
解释 jsonp 的原理,为何它不是真正的ajax ?
document load 和 ready 的区别
== 和 === 的不同
函数声明和函数表达式的区别
new Object() 和 Object.create()的区别
关于 this 的场景题
关于作用域和自由变量的场景题-1
判断字符串以字母开头,后面字母数字下划线,长度 6 - 30
关于作用域和自由变量的场景题-2
手写字符串 trim 方法,保证浏览器兼容性
如何获取多个数字中的最大值
如何用JS实现继承?
如何捕获JS程序中的异常?
什么是JSON?
获取当前页面的url 参数
将url 参数解析为JS对象
手写数组 flatern, 考虑多层级
数组去重
手写深拷贝
介绍一下 RAF requestAnimateFrame
前端性能如何优化?一般从哪几个方面考虑?
更多详情:前端知识体系
1. var 和 let const 的区别
var 是 ES5 语法, let const 是 ES6 语法; var 有变量提升
var 和 let 是变量,可修改;const 是常量,不可修改
let const 有块级作用域(ES6),var 没有
var 的变量提升:

// 变量提升 ES5
console.log(a) // undefined
var a = 200

var a
console.log(a) // undefined
a = 200

let 块级作用域:

// 块级作用域
for (let i = 0; i < 10; i++) {
    let j = i + 1
}
console.log(j)  // 报错

2. typeof 返回哪些类型
值类型:undefined string number boolean symbol
引用类型:object (注意: typeof null === ‘object’)
函数类型:function
3. 列举强制类型转换和隐式类型转换
强制:parseInt parseFloat toString 等
隐式:if 逻辑运算 == +拼接字符串
4. 手写深度比较,模拟 lodash isEqual
实现效果如下:

// 实现如下效果
const obj1 = {a:10, b:{ x: 100, y: 200}}
const obj1 = {a:10, b:{ x: 100, y: 200}}
isEqual(obj1, obj2) === true

// 判断是否是对象或数组
function isObject(obj) {
    return typeof obj === 'object' && obj !== null
}
// 全相等(深度)
function isEqual(obj1, obj2) {
    if (!isObject(obj1) || !isObject(obj2)) {
        // 值类型(注意,参与 equal 的一般不会是函数)
        return obj1 === obj2
    }
    if (obj1 === obj2) {
        return true
    }
    // 两个都是对象或数组,而且不相等
    // 1. 先取出 obj1 和 obj2 的 keys ,比较个数
    const obj1Keys = Object.keys(obj1)
    const obj2Keys = Object.keys(obj2)
    if (obj1Keys.length !== obj2Keys.length) {
        return false
    }
    // 2. 以 obj1 为基准,和 obj2 一次递归比较
    for (let key in obj1) {
        // 比较当前 key 的 val —— 递归!!!
        const res = isEqual(obj1[key], obj2[key])
        if (!res) {
            return false
        }
    }
    // 3. 全相等
    return true
}

// 测试
const obj1 = {
    a: 100,
    b: {
        x: 100,
        y: 200
    }
}
const obj2 = {
    a: 100,
    b: {
        x: 100,
        y: 200
    }
}
// console.log( obj1 === obj2 )
console.log( isEqual(obj1, obj2) )

const arr1 = [1, 2, 3]
const arr2 = [1, 2, 3, 4]

5. split() 和 join() 的区别
'1-2-3'.split('-')  // [1,2,3]
[1,2,3].join('-')   // '1-2-3'

6. 数组的 pop push unshift shift 分别做什么
功能是什么?
返回值是什么?
是否会对原数组造成影响?

const arr = [10, 20, 30, 40]

// pop
const popRes = arr.pop()
console.log(popRes, arr)  // 40  [10,20,30]

// shift
const shiftRes = arr.shift()
console.log(shiftRes, arr) // 10 [20,30,40]

// push
const pushRes = arr.push(50) // 返回 length
console.log(pushRes, arr)  // 5  [10,20,30,40,50]

// unshift
const unshiftRes = arr.unshift(5) // 返回 length
console.log(unshiftRes, arr) // 5 [5,10,20,30,40]

【扩展】数组的API,有哪些是纯函数?
纯函数:

不改变源数组(没有副作用);
返回一个数组
const arr = [10, 20, 30, 40]
1
// concat
const arr1 = arr.concat([50, 60, 70])
console.log(arr) // [10, 20, 30, 40]
console.log(arr1) //[10, 20, 30, 40, 50, 60, 70]

// map
const arr2 = arr.map(num => num * 10)
console.log(arr) // [10, 20, 30, 40]
console.log(arr2) //[100, 200, 300, 400]

// filter
const arr3 = arr.filter(num => num > 25)
console.log(arr) // [10, 20, 30, 40]
console.log(arr3) //[30, 40]

// slice
const arr4 = arr.slice()
console.log(arr) // [10, 20, 30, 40]
console.log(arr4) //[10, 20, 30, 40]

非纯函数

push pop shift unshift
forEach
some every
reduce
7. 数组 slice 和 splice 区别
功能区别 (slice - 切片,splice - 剪接)
参数和返回值
是否是纯函数
slice 纯函数
const arr = [10, 20, 30, 40, 50]

const arr1 = arr.slice()
console.log(arr1) // [10, 20, 30, 40, 50]

const arr2 = arr.slice(1, 4)
console.log(arr2) // [20, 30, 40]

const arr3 = arr.slice(2)
console.log(arr3) // [30, 40, 50]

const arr4 = arr.slice(-3)
console.log(arr4) // [30, 40, 50]

splice 非纯函数
const arr = [10, 20, 30, 40, 50]

// splice 非纯函数
const spliceRes = arr.splice(1, 2, 'a', 'b', 'c')
console.log(spliceRes, arr) //[20,30] [10, 'a', 'b', 'c', 40, 50]

const spliceRes1 = arr.splice(1, 2)
console.log(spliceRes1, arr)//[20,30] [10, 40, 50]

const spliceRes2 = arr.splice(1, 0, 'a', 'b', 'c')
console.log(spliceRes2, arr)//[] [10, "a", "b", "c", 20, 30, 40, 50]

8. [10,20,30].map(parseInt) 返回的结果是什么?
map 的参数和返回值
parseInt 参数和返回值
const res = [10, 20, 30].map(parseInt)
console.log(res) // [10, NaN, NaN]

拆解后等同于如下:

[10, 20, 30].map((num, index) => {
    return parseInt(num, index)
})

parseInt(10, 0) // 10
parseInt(10, 10) // 10
parseInt(20,1) // NaN
parseInt(30, 2) // NaN

9. ajax 请求 get 和 post 的区别?
Ajax, jQuery ajax, fetch,axios ヾ(⌐■_■)ノ看完 你就明白了~~

get 一般用于查询操作,post 一般用于提交操作
get 参数拼接在url 上,post 放在请求体内(数据体积可更大)
安全性:post 易于防止CSRF
10. call() apply() bind() 作用和区别
fn.call(this, p1, p2, p3)
fn.apply(this, arguments)
var fn1 = fn.bind(this, p1, p2, p3)
fn1()

相同点:

改变对象的执行上下文(总的来说,就是改变this的指向)。
this关键字,就是所谓的执行上下文。this关键字在函数中,表示的是一个指向,this的指向永远是一个对象。

都可以指定调用实参。

不同点:

call()和bind()的参数是直接连续传递,而apply传递参数是以一个数组传递。
bind()会返回一个方法。
注意:
如果call()和apply()的第一个参数是null或者undefined,那么this的指向就是全局变量,在浏览器里就是window对象。

代码演示:

var num = "全局中的num";
var o1 = {
    num:"o1中的num",
    f1:function(){
        console.log(this.num);
    },
    f2:function (a,b) {
        console.log(a+b);
        return a+b;
    }
}

var o2 = {
    num:"o2中的num"
}

o1.f1.call(o2); //输出:o2中的num
o1.f1.apply(o2);//输出:o2中的num
var f3 = o1.f1.bind(o2);
f3();//输出:o2中的num

o1.f2.call(o2,1,2); //输出:3
o1.f2.apply(o2,[1,2]);//输出:3
var f4 = o1.f2.bind(o2,1,2);
f4();//输出:3


11. 事件代理(委托)是什么?
js中事件冒泡我们知道,子元素身上的事件会冒泡到父元素身上。
事件代理就是,本来加在子元素身上的事件,加在了其父级身上。
那就产生了问题:父级那么多子元素,怎么区分事件本应该是哪个子元素的?
答案是:event对象里记录的有“事件源”,它就是发生事件的子元素。
它存在兼容性问题,在老的IE下,事件源是 window.event.srcElement,其他浏览器是 event.target
用事件委托有什么好处呢?
第一个好处是效率高,比如,不用for循环为子元素添加事件了
第二个好处是,js新生成的子元素也不用新为其添加事件了,程序逻辑上比较方便
const p1 = document.getElementById('p1')
const body = document.body
bindEvent(p1, 'click', e => {
        e.stopPropagation() // 注释掉这一行,来体会事件冒泡
        alert('激活')
})
bindEvent(body, 'click', e => {
        alert('取消')
})

12. 闭包是什么?有什么特性?有什么负面影响?
JS基础知识:作用域和闭包 ლ(´ڡ`ლ)一样的话题,一样的配方!

作用域和自由变量
闭包应用场景:作为参数被传入,作为返回值被返回
注意:自由变量的查找,要在函数定义的地方(而非执行的地方)
闭包影响:
变量会常驻内存,得不到释放。闭包不要乱用

13. 如何阻止事件冒泡和默认行为?
event.stopPropagation()
event.preventDefault()
14. 查找,添加,删除,移动DOM节点的方法
DOM操作 ᕙ༼ ͝°益° ༽ᕗ 就是这么吊!

15. 如何减少DOM操作?
DOM操作 ᕙ༼ ͝°益° ༽ᕗ 就是这么吊!

缓存DOM 查询结果
多次DOM操作,合并到一次插入


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马