js 基础要点

对象转基本类型

//Symbol.toPrimitive的优先级最高
let a = {
    valueOf(){
        return 0;
    },
    toString(){
        return '1';
    },
    [Symbol.toPrimitive](){
        return 2;
    }
}
1+a // =>3 
'1' + a //=>'12'
复制代码

四则运算符

1 + '1' //'11'
2 * '2' //4
[1,2] + [2, 1] //'1,22,1'
//[1,2].toString() ->'1,2'
//[2,1].toString() ->'2,1'
//'1,2' + '2,1' = '1,22,1'

'a' + + 'b'  //->"aNaN"
//+ 'b' --->NaN
//+ '1' ->1
复制代码

== 操作符

[] == ![] // -> true 解析如下
//[] 转成true ,然后取反变成 false 
[] == false 
则 [] == ToNumber(false)
则 [] == 0 
则 ToPrimitive([]) == 0
//[].toString() ->'''' == 0
则 0 == 0   ---> true 
复制代码

闭包

定义:函数A返回一个函数B,并且函数B中使用了函数A的变量,则函数B就被称为闭包

function A(){
    let a = 1
    function B(){
        console.log(a)
    }
    return B 
}
复制代码
经典面试题:循环中使用闭包解决var定义函数的问题

for( var i=1;i<=5; i++ ){
    setTimeout( function timer() {
        console.log( i );
    }, i*1000);
}

由于setTimeout 是个异步函数,所以会先把循环全部执行完毕,
这时 i 是6了
;所以会输出一堆的6 
复制代码
解决方法:

* 1.使用闭包
for (var i = 1; i <=5 ;i++ ){
   ( function(j){
        setTimeout(function timer() {
            console.log(j);
        }, j * 1000);
    })(i)
}


* 2.使用setTimeout的第三个参数
for (var i = 1; i <= 5; i++){
    setTimeout(function timer(j){
        console.log(j)
    }, i*1000, i);
}


* 3.使用 let定义 i
 for (let i = 1; i <= 5; i++ ){
     setTimeout( function timer(){
         console.log( i );
     },i*1000);
 }
复制代码

深浅拷贝

let  a = {
    age : 1
}
let b = a 
a.age = 2 
console.log(b.age) //2 

即 若给一个变量赋值一个对象,那么两者的值会是同一个
引用,其中一方改变,另一方也会相应的改变。

复制代码

解决以上问题方式如下:

浅拷贝: Object.assign 或 展开运算符 (浅拷贝只能解决第一层问题)

let a = {
    age : 1
}
let b = Object.assign({}, a) 或 let b = {...a}
a.age = 2 
console.log( b.age)   //1
复制代码

深拷贝 JSON.parse(JSON.stringify(object)

let a = {
    age : 1,
    jobs: {
        first:'FE'
    }
}
let b = JSON.parse(JSON.stringify(a)
a.jobs.first = 'native'
console.log(b.jobs.first) //FE

<!--局限性 会忽略undefined symbol ;
 不能序列化函数
 不能解决循环引用的对象-->
复制代码

![](https://user-gold-cdn.xitu.io/2019/1/1

模板化 在右Babel的情况下,可用直接使用ES6的模板化 commonJS是node独有的规范

防抖

在滚动事件中需要做一个复杂计算或者 实现一个按钮的方二次点击操作。

(频繁的事件回调中做复杂计算,很可能造成页面卡顿,所以不如将多次计算合并为一次计算,只在一个精确点做操作)

ps:防抖和节流 的作用是防止函数多次调用;区别:假设一个用户一直触发这个函数,且每次触发函数的间隔小于wait,防抖的情况下只会调用一次,而节流的情况 会每隔一定时间(参数wait)调用函数。

<!--
func 是用户传入需要防抖的函数
wait是等待时间
-->
const debounce = (func, wait = 50) =>{
   //缓存 一个定时器id
    let timer = 0 
    //
    return function(...args) {
        if(timer) clearTimeout(timer)
        timer = setTimeout(() =>{
            func.apply(this, args)
        },wait)
    }
}
复制代码
  • 搜索时,用户输入完最后一个字才调用查询接口, 延迟执行的 防抖函数
  • 点赞 如star是,立马反馈是否star成功,使用立即执行的防抖函数
function debounce (func ,wait = 50 ,immediate = true){
    let timer, context,args;
    const later = () =>setTimeOut(() => {
        timer = null 
        if(!immediate){
            func.apply(context,args)
            context = args = null
        }
    },wait)
    
    return function(...params) {
        if(!timer){
            timer =  later()
            if(immediate){
                func.apply(this,params)
            }else{
                context = this
                args = params
            }
        }else{
            clearTimeout(timer)
            timer = later()
        }
    }
}
复制代码

总结:

  • 对于按钮放点击来说的实现:如果函数是立即执行的,就立即调用,如果函数是延迟执行的,就缓存上下文和参数,放到延迟函数中去执行。一旦我开始一个定时器,只要我定时器还在,你每次点击我都重新计时。 一旦你点累,定时器时间到,定时器重置为null,就可以再次点击了。
  • 对于延迟执行函数来说的实现:清除定时器id,如果是延迟调用就调用函数

节流

节流和防抖动的本质是不一样的。防抖动是 多次执行变成最后一次执行,节流是将多次执行变成每隔一段时间执行。

继承

class MyDate extend Date{
    test(){
        rreturn this.getTime()
    }
}
let myDate = new MyDate()
myDate.test()
复制代码

需要用Babel来编译代码 底层限制:若不是Date构造出来的实例,就不能调用Date的函数

function MyData(){
    
}
MyData.prototype.test = function(){
    retrun this.getTime()
}
let d = new Date()
Object.setPrototypeOf(d,MyData.prototype)
Object.setPrototypeOf(MyData.prototype,Date.prototype)
即先创建父类实例 =》 改变实例原先的_proto_转而连接到子类的prototype=》
子类的prototype的 _proto_改为父类的prototype
通过这种方式实现的继承可以完美解决 JS底层限制
复制代码

call ,apply ,bind区别

call和apply: 都是为了解决改变this的指向,只是传参的方式不同。 除了第一个参数外,call可以接收一个参数列表, apply只接受一个参数数组。 bind:作用也是解决改变this的指向,只是该方法返回一个函数。

let a = {
    value:1
}
function getValue(name ,age){
    console.log(name)
      console.log(age)
        console.log(this.value)
    
}
getValue.call(a,'yck','24')
getValue.apply(a,['yck','24'])
复制代码

Promise 实现

Promise是Es6 新增的语法,解决了回调地狱的问题 看成一个状态机: 初始pending,通过函数resolve 和reject 将状态改成了 resolved和 rejected 状态,并且状态一旦改变就不能再次变化

then函数会返回一个Promise实例,并且该返回值是一个新的实例而不是之前的实例。因为Promise规范规定处理pending状态,其他状态是不可以改变的, 所以then本质上可以看成是 flatMap

Generator实现

Generator是ES6中新增的语法,都可以异步编程。

function* test(){
    let a = 1+2;
    yield 2;
    yield 3;
}
let b = test();
console.log(b.next()
复制代码

转载于:https://juejin.im/post/5c369b6051882524a1414f71

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值