JavaScript汇总

485 阅读8分钟

js

js中的数据类型

基本类型:number string boolean null undefined symbol bigint

引用数据类型:object (包含,Date,RegExp,Function,Array,Math..)

在 ES6 中新增的 Symbol 类型,代表创建后独一无二且不可变的数据类型,它的出现我认为主要是为了解决可能出现的全局变量冲突的问题

两种类型的区别是: 存储位置不同

原始数据类型直接存储在栈(stack)中的简单数据段, 占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储。

引用数据类型存储在堆(heap) 中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

作用域 变量提升

函数执行时的作用域

解构赋值

ES 6 语法知道哪些,分别怎么用?

ES6、ES7、ES8特性一锅炖(ES6、ES7、ES8学习指南)

class

  1. 在类中声明方法的时候,千万不要给该方法加上function关键字
  2. 方法之间不要用逗号分隔,否则会报错
  3. 类实质上就是一个函数。类自身指向的就是构造函数。所以可以认为ES6中的类其实就是构造函数的另外一种写法! console.log(Person===Person.prototype.constructor);//true
  4. 类的所有方法都定义在类的prototype属性上
  5. constructor方法是类的构造函数的默认方法,通过new命令生成对象实例时,自动调用该方法。
  6. constructor方法如果没有显式定义,会隐式生成一个constructor方法。所以即使你没有添加构造函数,构造函数也是存在的。
    constructor方法默认返回实例对象this,但是也可以指定constructor方法返回一个全新的对象,让返回的实例对象不是该类的实例。
  7. constructor中定义的属性可以称为实例属性(即定义在this对象上),
    constructor外声明的属性都是定义在原型上的,可以称为原型属性(即定义在class上)。
    hasOwnProperty()函数用于判断属性是否是实例属性。其结果是一个布尔值, true说明是实例属性,false说明不是实例属性。
    in操作符会在通过对象能够访问给定属性时返回true,无论该属性存在于实例中还是原型中。
  8. 通过proto来为类增加方法。使用实例的proto属性改写原型,会改变Class的原始定义,影响到所有实例,所以不推荐使用!
  9. class不存在变量提升,所以需要先定义再使用。因为ES6不会把类的声明提升到代码头部,但是ES5就不一样,ES5存在变量提升,可以先使用,然后再定义。

箭头函数都有哪些特点?

  1. 箭头函数是匿名函数.

  2. 不能作为构造函数,不能使用new

    let foo=()=>{}
    var newFoo=new foo() //foo is not a construcotr
    
  3. 箭头函数没有原型对象

  4. 不能使用argumetns,取而代之用rest参数...解决

    let C = (...c) => {
      console.log(c);
    }
    C(1,2,3,3)
    
  5. 不绑定this

    会捕获其定义时所在的this指向作为自己的this。由于在vue中自动绑定 this 上下文到实例中,因此不能使用箭头函数来定义一个周期方法。 箭头函数的this永远指向上下文的this,call、apply、bind也无法改变

babel ES6 转换 ES5 实现原理

如何判断变量的类型

Array.isArray
typeof
instanceof
constructor:此属性返回对创建此对象的数组函数的引用 console.log(arr.constructor === Array); //true Object.prototype.toSting
一般只有回答了Object.prototype.toSting这个答案,才算完事

this的指向有哪几种?分别说出来

改变this指向有哪几种方式?(call,apply,bind以及他们的区别)

闭包是什么?哪些地方用到了闭包?写出一个闭包

回答完闭包的概念,可以说防抖、节流就用到了闭包,
一般面试官会接着问你,可以把自己准备的防抖、节流说一下,有的让你手写实现

原型是什么? 原型链是什么?

原型是什么? 原型链是什么?

  1. 所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象

  2. 所有函数都有一个prototype(原型)属性,属性值是一个普通的对象

  3. 所有引用类型的__proto__属性指向它构造函数的prototype

var a = [1,2,3]; a.proto === Array.prototype; // true

原型链

当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链

原型链最顶层Object的prototype的__proto__指向为null

image.png

什么是浅拷贝和深拷贝?

相关文章

Event Loop 机制

很重要啊,必会啊!!!!!

promise 打印面试题

js异步发展史

围绕这几个描述: ajax、promise、generator、async await

async await 怎么用?实现原理是什么 ?

async await 如何捕获异常

回调函数的坏处

数组api背熟(哪几个可以改变原数组,每一个的返回值最好记住)

map forEach filter的区别(知道上面这个题,这个就没啥问题)

every some的区别(知道上上面这个题,这个就没啥问题)

reduce (好好看一下)

内存泄漏

setTimeout模拟setInterval

CommonJS、AMD、CMD和ES6模块化区别

js如何实现继承

创建对象的6种方式总结

js的设计模式

发布订阅

单例、工厂、构造函数、发布订阅

订阅发布、观察者,会的越多越好,回答这种题,最好往自己擅长的地方回答,被动变主动, 比如vue的双向数据绑定就是用的订阅发布,不要只干干的回答问题,要会拓展,会延伸

DOM事件流和事件委托

相关文章

越来越火的网络请求Fetch和Axios到底有什么区别

ajax,axios,fetch的区别是什么?

axios是什么?axios如何实现原理?

axios 之cancelToken原理以及使用

图片懒加载

讲vue-lazyloader的原理,手写伪代码, 源码以及设计

函数式编程

用JavaScript的异步实现sleep函数

js 控制最大请求数(快手手写题目)

字节跳动面试官:请你实现一个大文件上传和断点续传

广度遍历 & 深度遍历

类型转换

symbol的作用

for in 和 for of的区别

相关文章: blog.csdn.net/margin_0px/…

  1. 优先迭代数字属性
  2. 会遍历所有私有的和公有的可枚举属性(性能最差的循环)
  3. 无法迭代symbol类型的私有属性(告别for in)
        let keys = Object.getOwnPropertyNames(obj);
        keys = keys.concat(Object.getOwnPropertySymbols(obj));
        keys.forEach(key =>{console.log(key)})
    

requestAnimationFrame的优势

www.jianshu.com/p/fa5512dfb…

相关文章:

juejin.cn/post/684490…

juejin.cn/post/684490…

手写题汇总

手写new, new操作符都做了些什么

手写 bind

//手写apply
Function.prototype.myApply = function (context, args) {
    //这里默认不传就是给window,也可以用es6给参数设置默认参数
    context = context || window
    args = args ? args : []
    //给context新增一个独一无二的属性以免覆盖原有属性
    const key = Symbol()
    context[key] = this
    //通过隐式绑定的方式调用函数
    const result = context[key](...args)
    //删除添加的属性
    delete context[key]
    //返回函数调用的返回值
    return result
}
//手写call
//传递参数从一个数组变成逐个传参了,不用...扩展运算符的也可以用arguments代替
Function.prototype.myCall = function (context, ...args) {
    //这里默认不传就是给window,也可以用es6给参数设置默认参数
    context = context || window
    args = args ? args : []
    //给context新增一个独一无二的属性以免覆盖原有属性
    const key = Symbol()
    context[key] = this
    //通过隐式绑定的方式调用函数
    const result = context[key](...args)
    //删除添加的属性
    delete context[key]
    //返回函数调用的返回值
    return result
}
Function.prototype.myBind = function (context, ...args) {
    const fn = this
    args = args ? args : []
    return function newFn(...newFnArgs) {
        return fn.apply(context, [...args,...newFnArgs])
    }
}

手写promise

手写promise.all、 promise.race

考察promise.all, promise.race的最多,必须会


    Promise.all = function(arr) {
        let res = [];
        return new Promise((resolve, reject) => {
            for(let i=0; i< arr.length; i++) {
                Promise.resolve(arr[i]).then(data => {
                    i++;
                    res[i] = data;
                    if(i === arr.length) {
                        return resolve(res);
                    }
                }, err => {
                    return reject(err);
                });
            }
        })
    }
    

手写防抖、节流

手写防抖、节流(背下来,必会!!!)

手写ajax

手写深拷贝

相关文章

    function deepClone(targetObj) {
	let type = Object.prototype.toString.call(targetObj);
	let newObj;
	if (type === "[object Object]") {
	  newObj = {};
	} else if (type === "[object Array]") {
	  newObj = [];
	} else {
	  return targetObj;
	}
	for(key in targetObj) {
	    let value = targetObj[key];
	    newObj[key] = deepClone(value);
	}
	return newObj;
    }
    // 用map处理循环引用的问题
    function cloneDeep(obj, hash = new WeakMap()) {
      if(Object.prototype.toString.call(obj) !== '[object Object]') return obj;
      if(hash.get(obj)) return hash.get(obj);
      let cloneObj = {};
      hash.set(obj, cloneObj);
      for(let key in obj) {
        if(obj.hasOwnProperty(key)) {
          cloneObj[key] = cloneDeep(obj[key], hash);
        }
      }
      return cloneObj;
    }
    let obj = { name: 1, address: { x: 100 } };
    obj.o = obj; // 对象存在循环引用的情况
    let d = cloneDeep(obj);
    obj.address.x = 200;
    console.log(d);

手写event bus

相关文章

手写instanceof实现原理

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

function instance_of(L, R) {
    var O = R.prototype; 
    L = L.__proto__;
    while (true) {    
        if (L === null)      
             return false;   
        if (O === L) 
             return true;   
        L = L.__proto__;  
    }
}

代码解释:

①L表示对象实例,R表示构造函数或者父类型实例

②取R的显式原型,取L的隐式原型

③循环遍历,进行判断②中的两个值是否相等,相等返回true,不相等继续查找L的原型链

参考: zhuanlan.zhihu.com/p/105487552

手写axios

手写curry

function curry(fn) {
    let judge = (...args) => {
        if (args.length == fn.length) return fn(...args)
        return (...arg) => judge(...args, ...arg)
    }
    return judge
}

function add(a, b, c) {
    return a + b + c
}
add(1, 2, 3)
let addCurry = curry(add)
addCurry(1)(2)(3)

手动实现parseInt

手动实现一个find, findIndex

手写实现map

Array.prototype.copyMap = function (fn, toThis) { 
    let arr = this; 
    const result = [];
    const redirectThis = toThis || Object.create(null); 
    for (let i = 0; i < arr.length; i++) { 
        const item = fn.call(redirectThis, arr[i], i, arr); 
        result.push(item); 
    } 
    return result;
}

如何安全的获取Object深层对象