Giter VIP home page Giter VIP logo

blog's Introduction

blog's People

Contributors

aochengcheng avatar

Watchers

 avatar

blog's Issues

javascript手写面试题

1.数组去重

原始类型,引用类型不可用

  • Set方法
    let a = [...new Set(arr)]
  • 使用filter
    arr.filter((item, i, array) => array.indexOf(item) === i)
  • 使用reduce
    arr.reduce((pre, cur) => pre.includes(cur) ? pre : [...pre, cur] , [])
  • 使用Object键值对
    function unique(arr) {
    let obj = {}
    return arr.filter((item, index, array) => {
    return obj.hasOwnProperty(typeof item + item) ? false : obj[typeof item + item] = item
    })
    }

2.实现数组flat

将多维数组降为一维数组

  let flatDeep = (arr) => {
  return arr.reduce((pre, cur) =>  Array.isArray(cur) ? [...pre, ...flatDeep(cur)] : [...pre, cur], [])
 }

写一个高级一些的flatDeep

  let flatDeep = (arr, d = 1) => {
    return d > 0 ? arr.reduce((pre, cur) => pre.concat(Array.isArray(cur) ? flatDeep(cur, d - 1) : cur) , []) : arr.slice()
  }

3.深拷贝

浏览器Event-loop

javascript 运行机制

  1. 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)
  2. 主线程之外,还存在任务队列(stack queue),只要异步任务有了运行结果,就在任务队列中放置一个事件。
  3. 一旦执行栈中所有的同步任务执行完毕,系统就会读取任务队列,看看里面有哪些事件。那些对应的异步任务结束等待,进入执行栈,开始执行。
  4. 主线程不断执行上面的三步。

总结就是:

调用栈中的同步任务都执行完毕,栈内被清空,系统会读取任务队列,按照顺序读取一个任务放入栈中执行。 每次栈内被清空,都会去查看任务队列有没有任务,有就读取执行。
一个事件循环中有一个或者多个任务队列

javascript有两种异步任务

  • 宏任务: script(整体代码) setTimeout, setInterval, setImmediate, I/O, UI rendering
  • 微任务:process.nextTick(nodejs) , Promise, Object.observe, MutationObserver

2.事件循环(Event-loop)是什么

主线程从‘任务队列’中读取执行事件,这个过程是循环不断的,这个机制被称为事件循环。
此机制如下: 主线程会不断从任务队列中按顺序读取任务执行,每执行完一个任务都会检查microtask队列是否为空(执行完一个任务的具体标志是函数执行栈为空),如果不为空则会一次性执行完所有microtask。然后再进入下一个循环去任务队列中取下一个任务执行。

js常用的几个操作

基本数据类型有哪几种? null是对象吗? 值类型和引用类型存储的区别。

  • 原始类型有6种:
    • Undefined
    • null
    • bool
    • string
    • number
    • Symbol (ES6)
  • typeof null 返回object 但是null不是对象,而是基本数据类型
  • 值类型存储在盏内存中,存储的是值
  • 引用类型存储在堆内存中,存储的是地址。当把一个对象赋值给另外一个变量时,赋值的是地址,指向同一块内存空间,当其中一个对象改变时,另一个也会改变。

Typeof 是否正确判断类型? instanceOf ? instanceOf的实现原理

typeof 只会正确判断基本数据类型,但是除了null typeof null 返回object

对于对象,typeof不能正确判断其类型,typeof 一个函数可以输出 function ,除此之外,输出的全是object。

如何准确判断 js 的数据类型

typeof 无法判断准确判断复杂数据类型

Instanceof 无法正确判断基本数据类型

for of , for in 和 forEach,map 的区别。

  • for...of循环:具有 iterator 接口,就可以用for...of循环遍历它的成员(属性值)。for...of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象、Generator 对象,以及字符串。for...of循环调用遍历器接口,数组的遍历器接口只返回具有数字索引的属性。对于普通的对象,for...of结构不能直接使用,会报错,必须部署了 Iterator 接口后才能使用。可以中断循环。
  • for...in循环:遍历对象自身的和继承的可枚举的属性, 不能直接获取属性值。可以中断循环。
  • forEach: 只能遍历数组,不能中断,没有返回值(或认为返回值是undefined)。
  • map: 只能遍历数组,不能中断,返回值是修改后的数组。

如何判断一个变量是不是数组

  • 使用 Array.isArray 判断,如果返回 true, 说明是数组
  • 使用 instanceof Array 判断,如果返回true, 说明是数组
  • 使用 Object.prototype.toString.call 判断,如果值是 [object Array], 说明是数组
  • 通过 constructor 来判断,如果是数组,那么 arr.constructor === Array. (不准确,因为我们可以指定 obj.constructor = Array)

call , apply 有什么区别? call、apply、bind内部是如何实现的?

call 和 apply 的功能相同,区别在于传参的方式不一样:

  • fn.call(obj, arg1, arg2, ...),调用一个函数, 具有一个指定的this值和分别地提供的参数(参数的列表)。
  • fn.apply(obj, [argsArray]),调用一个函数,具有一个指定的this值,以及作为一个数组(或类数组对象)提供的参数。

call核心:

  • 将函数设为传入参数的属性
  • 指定this到函数并传入给定参数执行函数
  • 如果不传入参数或者参数为null,默认指向为 window / global
  • 删除参数上的函数
Function.prototype.call = function(context) {
  // 如果传入的第一个参数是 null/undefined,那么this指向 window/global
  // 如果第一个参数不是 null/undefined ,那么必须是一个 对象 
  
  if (!context) {
    contexgt = typeof window === 'undefined' ? global : window
  }
  
  context.fn = this   //this指向当前的函数
  let args = [...arguments].slice(1) // 截取除了第一个参数外的 其他参数
  let result = context.fn(...args)//隐式绑定,当前函数的this指向了context.
  delete context.fn
  return result
}

apply :

apply的实现跟call很相似,但是要注意他们的参数,apply 的第二个参数是数组 或 类数组

Function.prototype.apply = function(context, rest=[]) {
  if (!context) {
    context = typeof window === 'undefined' ? global : window
  }
  
  context.fn = this
  let result
  if (rest === undefined || rest === null) {
    result = context.fn(rest)	
  } else if (typeof rest === 'object') {
    result = context.fn(...rest)
  }
  delete context.fn
  return result
}

什么是深拷贝? 深拷贝和浅拷贝有什么区别?

浅拷贝只是复制第一层对象,但是当对象的属性是一个引用类型时,实质赋值的是引用,当引用的值发生改变会跟随变化

深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。深拷贝后的对象与原来的对象是完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象。

手写bind

this的四种绑定规则

  1. 默认绑定
    独立调用函数时, this 指向全局对象,如果使用严格模式,那么全局对象无法使用默认绑定, this 绑定至 undefined 并抛错

  2. 隐式绑定
    当函数作为引用属性被添加到对象中,隐式绑定规则会把函数调用中的 this 绑定到这个上下文对象

  3. 显式绑定
    运用apply call 方法,在调用函数时候绑定this,也就是指定调用的函数的this值

  4. new绑定
    就是使用new操作符的时候的this绑定

优先级:new绑定 > 显式绑定 > 隐式绑定 > 默认绑定

MDN 给出bind方法的定义:
bind() 方法创建一个新函数,当这个新函数被调用时其this置为提供的值。,其参数列表前几项置为创建时指定的参数序列。

bind() 函数会创建一个新 绑定函数 , 绑定函数 与被调函数具有相同的函数体(在 ECMAScript 5 中)。调用 绑定函数 通常会导致执行 包装函数 绑定函数 也可以使用new运算符构造:这样做就好像已经构造了目标函数一样。提供的 this 值将被忽略,而前置参数将提供给模拟函数

总的来说bind有如下三个功能点:

  1. 改变原函数的 this 指向,即绑定上下文,返回原函数的拷贝
  2. 当 绑定函数 被调用时,bind的额外参数将置于实参之前传递给被绑定的方法。
  3. 注意,一个 绑定函数 也能使用 new 操作符创建对象,这种行为就像把原函数当成构造器,thisArg 参数无效。也就是 new 操作符修改 this 指向的优先级更高。

开始实现一个bind

输入:接受一个或多个参数,第一个是要绑定的上下文,额外的参数当做绑定函数的参数。
输出:返回原函数的拷贝,即返回一个函数,这个函数具有原函数一样的功能

 Function.prototype.myBind = function(context, ...arg1) {
     if (typeof this !== 'function') throw new TypeError('not a function')
    const _self = this
    const fnNop = function () {} // 定义一个空函数
    function rf(...arg2){
       const args = [...arg1, ...arg2]
       const _this = this instanceof rf ? this : context
       _self.apply(_this, args)
    }
   fnNop.prototype = _self.prototype
   rf.prototype = new fnNop()
   return _self
 }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.