js基础知识积累

294 阅读4分钟

1.实现 (5).add(3).minus(2) //6

~(function (){
    function check(n){
        n=Number(n)
        return isNaN(n)?0:n
    }
   function add(n){
        n=check(n)
        return this+n
    }
    function minus(n){
        n=check(n)
        return this-n
    }
  
    Number.prototype.add=add
    Number.prototype.minus=minus
})()

2.箭头函数没有自己的this ,this指向当前函数执行的上下文,且无法用call apply bind 改变指向

function fn(){
    console.log(this)
}
document.body.onclick=fn //this指向body
function fn(){
    console.log(this)
}
document.body.onclick=fn.call(window)   //call会不等点击就立即执行,this指向window
function fn(){
    console.log(this)
}
document.body.onclick=fn.bind(window)   //点击之后打印window
let fn=()=>{
    console.log(this)
}
document.body.onclick=fn   //点击后打印window而不是body而且不能用call和bind改变
let fn=()=>{
    console.log(this)
}
document.body.onclick=fn.bind({})  //还是打印window   箭头函数this无法改变

3.箭头函数没有自己的arguments 可用(...arg) 代替

4.箭头函数不能作为构造函数 用new关键字执行 会报错(箭头函数没有 this,也没有prototype 属性,也没有自己的constructor构造函数)

5.正则匹配字符串中的字母,大写转小写 小写转大写,

let str='abcDE677#%yut987RFV'
str=str.replace(/[a-zA-Z]/g,(item)=>{
    if(item.toUpperCase()===item){
        return item.toLowerCase()
    }else{
        return item.toUpperCase()
    }
})
//ABCde677#%YUT987rfv
/abc(?=8)/
let str='abc8lgknhl'

6,正则,必须包含大小写字母 数字的6-16位字符串

let reg=/(?!^[a-zA-Z]+$)(?!^[a-z0-9]+$)(?!^[A-Z0-9]+$)^[a-zA-Z0-9]{6,16}$/;

7.收集一个滚动列表插件

 listMove(id, t = 2000) {
        var $uList = $(id);
        var timer = null;
        //触摸清空定时器
        $uList
            .hover(
                function () {
                    clearInterval(timer);
                },
                function () {
                    //离开启动定时器
                    timer = setInterval(function () {
                        scrollList($uList);
                    }, t);
                }
            )
            .trigger("mouseleave"); //自动触发触摸事件
        //滚动动画
        function scrollList(obj) {
            //获得当前<li>的高度
            var scrollHeight = $(`${id} .item:first`).height();
            //滚动出一个<li>的高度
            $uList.stop().animate(
                {
                    marginTop: -scrollHeight
                },
                700,
                function () {
                    //动画结束后,将当前<ul>marginTop置为初始值0状态,再将第一个<li>拼接到末尾。
                    $uList
                        .css({
                            marginTop: 0
                        })
                        .find(".item:first")
                        .appendTo($uList);
                }
            );
        }
    }

挂载到vue原型上

export default {
    install: function (vm) {
        vm.prototype.$listMove = listMove 
    }
}

8.数组扁平化加去重

let arr=[1,2,[3,4,[3,5],[55,5]],[3,5],9]
console.log([...new Set(arr.flat(Infinity))])

9.new关键字做了那些事情?自己实现一个_new方法

1.像普通函数执行一样形成一个私有作用域 ..形参赋值 ..变量提升 2.默认创建一个对象,让函数中的this指向这个对象,这个对象事当前类的实例 3.代码执行 4.把当前对象返回

function Dog(name){
    this.name=name
}
functon _new(CLA,...arg){
    //let obj={}
    //obj.__proto__=CLA.prototype
    let obj=Object.create(CLA.prototype)
    CLA.call(obj,...arg)
    return obj
}
let d1=_new(Dog,'aaa')
let d2=new Dog('bbb')

10.闭包,我理解的闭包概念

函数执行后形成了不被销毁的栈内存,保存了私有变量,就是闭包

var i=5
function fn(i){
    return function (n){
        console.log(n+(++i))
    }
}
var f=fn(1)
f(2) //4
fn(3)(4) //8
fn(5)(6) //12
f(7) //10
console.log(i)//5
var i=20
function fn(){
    i-=2;
    return function (n){
        console.log((++i)-n)
    }
}
var f=fn()
f(1) //18
f(2)//18
fn()(3)//16
fn()(4)//14
f(5)//14
console.log(i)//19

这两个很变态的闭包练习题,我终于搞通了

11,常用es6特性

1,let const 块级作用域
2,解构赋值 let [a,b]=[2,3]
3,对象合并 object.assigin(obj1,obj2)
3,promise 对象
4,对象的导入导出 import export

12,call bind apply 区别

call把函数当作普通函数执行,函数中的this指向call执行时的第一个参数,后面的参数当作普通参数传递给函数,如果一个参数都没有,在非严格模式下 this指向window 严格模式下指向undefind,如果传参null或者undefind,非严格模式下指向window,严格模式下写谁就指向谁,自己实现call方法

Function.prototype.call=function (context){
    let args=[...arguments]
    context=context||window
    context.$fn=this
    args=args.slice(1)
    let n=context.$fn(...args)
    delete context.$fn
    return n
}
let obj={a:111}
function fn(m,n){
    console.log(this) //{a: 111, $fn: ƒ}
    return m+n
}
let a=fn.call(obj,10,20)
console.log(a) //30

apply和call用法和效果一样,只是又一点不同,apply的第二个及其以后的参数要是个数组

Function.prototype.apply=function (context){
    context=arguments[0]
    context=context||window
    context.$fn=this
    args=arguments[1]
    let n=context.$fn(...args)
    delete context.$fn
    return n
}
let obj={a:111}
function fn(m,n){
    console.log(this) //{a: 111, $fn: ƒ}
    return m+n
}
let a=fn.apply(obj,[10,20])
console.log(a) //30

bind 返回一个函数,不会立即执行

Function.prototype.bin=function (context){
    context=context||window
    let args=[...arguments][1]
    context.$fn=this
    return function (){
        context.$fn(...args)
        delete context.$fn
    }
}

let obj={a:11}
function fn(a,b){
    console.log(this,a+b)
}
let f=fn.bin(obj,[2,9])
f() //11

13.重写一下数组的方法

Array.prototype._each=function (callback){
    for(let i=0;i<this.length;i++){
        callback(this[i],i)
    }
}
Array.prototype._map=function (callback){
    let newarr=[]
    for(let i=0;i<this.length;i++){
        newarr.push(callback(this[i],i))
    }
    return newarr
}
Array.prototype._fillter=function (callback){
    let newarr=[]
    for(let i=0;i<this.length;i++){
        let bl=callback(this[i],i)
        if(bl){
            newarr.push(this[i])
        }
    }
    return newarr
}

14,函数重载和重写

函数名相同,函数的参数个数和类型不同,叫函数重载,前端没有函数重载概念,可以在函数内判断实现,重载是后端语言为了减轻并发压力实现的方法,typescript也实现了函数的重载

function fn(a){}
function fn(a,b){}
function fn(a,b,c){}

重写是类的继承中 子类可以重写父类中的方法

15,javascript 中的设计模式

1,单例模式
2,工厂模式
3,组合模式,原型模式
4,订阅发布模式
5,观察者模式

16,js判断对象为空的常用方法

1,JSON.stringfy(obj)=="{}"
2,object.keys(obj).length

17, Object.create 的作用,手写一个create函数

1.他会生成一个新的空对象
2.这个空对象可以继承目标对象的属性和方法

let obj={a:1}
function create(O){
    let f={}
    f.prototype=O
    return f
}
let b=create(obj)
console.log(b,b.a)//{},1

18,js实现冒泡排序

function sort(arr){
    let newArr=[...arr]
    let len=newArr.length
    for(let i=0;i<len-1;i++){
        for(let j=0;j<len-1-i;j++){
            if(newArr[j]>newArr[j+1]){
                [newArr[j],newArr[j+1]]=[newArr[j+1],newArr[j]]
            }
        }
    }
    return newArr //返回一个排序后的新数组
}

myArr = [20,18,27,19,35];
let arr2=sort(myArr)
console.log(myArr,arr2)

19.js数据类型转换的方法

再js中数据类型转换有三种情况,
转换未布尔Boolean()
转为数字Number(),ParseInt(),ParseFloat()
转为字符串toString(),String()
null和undefined不可调用toString()方法。

20.js中判断数据类型的方法

typeof instandof Object.prototype.toString.call()

21,js有哪些内置对象

1),值属性,这些全局属性返回一个简单值这些值没有自己的属性和方法例如:Infinity,NaN,undefined,null
2).函数属性:parseInt(),parseFloat(),eval()
3).基本对象,Object Function Boolean Symbol Error
4).数字和日期对象,Number Math Date
5),字符串对象 String RegExp
6),可索引对象Array
7),结构化数据 JSON
8),控制抽象对象,Promise , Generator
9)反射,Reflect , Proxy
10),...

22,递归实现1到100求和

function sum(){
    let result=0
    let i=1
    return function calc(){
        result+=i++
        return i>100?result:calc()
    }()
}

23.防抖和节流

防抖是一个频繁执行的事件我只需要最后一次的结果

let debounce = (fn, delay) => {
    let timer = null;
    return (...args) => {
        clearTimeout(timer);
        timer = setTimeout(() => {
            fn.apply(this, args);
        }, delay);
    }
}

节流是降低频繁事件的执行频率

let throttle = (fn, delay) => {
    let flag = true;
    return (...args) => {
        if (!flag) return;
        flag = false;
        setTimeout(() => {
            flag = true;
            fn.apply(this, args);
        }, delay);
    }
} 

24,数据类型检测

typeof
constructor
instandof
Object.prototype.toString.call()

25,this 的三种使用场景

1.全局下的this 非严格模式下指向window 严格模式指向 undefind
2.构造函数中的this 指向实例
3.方法中的this指向带哦用此方法的对象

26 正则去空格的常用方法

//去除空格 
String.prototype.Trim = function() { 
return this.replace(/\s+/g, ""); 
} 

//去除换行 
function ClearBr(key) { 
key = key.replace(/<\/?.+?>/g,""); 
key = key.replace(/[\r\n]/g, ""); 
return key; 
} 

//去除左侧空格 
function LTrim(str) { 
return str.replace(/^\s*/g,""); 
} 

//去右空格 
function RTrim(str) { 
return str.replace(/\s*$/g,""); 
} 

//去掉字符串两端的空格 
function trim(str) { 
return str.replace(/(^\s*)|(\s*$)/g, ""); 
} 

//去除字符串中间空格 
function CTim(str) { 
return str.replace(/\s/g,''); 
} 

//是否为由数字组成的字符串 
function is_digitals(str) { 
var reg=/^[0-9]*$/; //匹配整数 
return reg.test(str); 
}

27 js检测一个变量是string

1 typeof x === "string"
2 typeof(x) === "string"    // 小写
3 x.constructor === String     // 大写类型

28 异步函数

async function async1 () {
  console.log('async1 start')
  await async2(); console.log('async1 end')
}
async function async2 () {
  console.log('async2')
}
console.log('script start')
setTimeout(function () {
  console.log('setTimeout')
}, 0)
async1()
new Promise(function (resolve) {
  console.log('promise1')
  resolve()
}).then(function () {
  console.log('promise2')
})
console.log('script end')


29 js 宏任务,微任务,执行顺序

宏任务: js宿主 全局任务 setTimeOut,setInterval,setImmediate, I/O render
微任务: js自己的任务,process.nextTick (node.js中进程相关的对象), Promise, Object.observer, MutationObserver
宏任务队列可以有多个,微任务队列只有一个,微任务优先于宏任务执行

30,得到两个数组的交集,两个数组的元素为数字或者字符串

function getIntersection(arr1,arr2)=>{
    let len = arr1.length < arr2.length ? arr1.length : arr2.length;
    let i = -1;
    let res = [];
    if (arr1.length < arr2.length) {
        while( ++1 < len ) {
            const item = arr1[i];
            if (arr2.indexOf(item) > -1) res.push(item)
        }
    } else {
        while( ++1 < len ) {
            const item = arr2[i];
            if (arr1.indexOf(item) > -1) res.push(item)
        }
    }
    
}