GithubHelp home page GithubHelp logo

blog's Introduction

blog's People

Contributors

aochengcheng avatar

Watchers

 avatar

blog's Issues

手写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
 }

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.深拷贝

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
}

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

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

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

浏览器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。然后再进入下一个循环去任务队列中取下一个任务执行。

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.