字节跳动最爱考的前端

0.1 + 0.2 === 0.3 嘛?为什么?

JavaScirpt 使用 Number 类型来表示数字(整数或浮点数),
遵循 IEEE 754 标准,
通过 64 位来表示一个数字(1 + 11 + 52)
1 符号位,0 表示正数,1 表示负数 s
11 指数位(e)
52 尾数,小数部分(即有效数字)
最大安全数字:Number.MAX_SAFE_INTEGER = Math.pow(2, 53) - 1,
转换成整数就是 16 位,所以 0.1 === 0.1,是因为通过 toPrecision(16) 
去有效位之后,
两者是相等的。

在两数相加时,会先转换成二进制,0.1 和 0.2 转换成二进制的时候尾数会
发生无限循环,
然后进行对阶运算,JS 引擎对二进制进行截断,所以造成精度丢失。

所以总结:精度丢失可能出现在进制转换和对阶运算中
实现函数能够深度克隆基本类型

function shallowClone(obj) {
  let cloneObj = {};
  
  for (let i in obj) {
    cloneObj[i] = obj[i];
  }
  
  return cloneObj;
}
深克隆

function deepCopy(obj) {
  if (typeof obj === 'object') {
    var result = obj.constructor === Array ? [] : {};
    
    for (var i in obj) {
      result[i] = typeof obj[i] === 'object' ? 
      deepCopy(obj[i]) : obj[i];
    }
  } else {
    var result = obj;
  }
return result;
}  

事件流

事件流是网页元素接收事件的顺序,"DOM2级事件"规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。首先发生的事件捕获,为截获事件提供机会。然后是实际的目标接受事件。最后一个阶段是时间冒泡阶段,可以在这个阶段对事件做出响应。虽然捕获阶段在规范中规定不允许响应事件,但是实际上还是会执行,所以有两次机会获取到目标对象。

事件冒泡

我是父元素 我是子元素

parEle.addEventListener(‘click’, function () {
alert(‘父级 冒泡’);
}, false);
parEle.addEventListener(‘click’, function () {
alert(‘父级 捕获’);
}, true);

sonEle.addEventListener(‘click’, function () {
alert(‘子级冒泡’);
}, false);
sonEle.addEventListener(‘click’, function () {
alert(‘子级捕获’);
}, true);

当容器元素及嵌套元素,即在捕获阶段又在冒泡阶段调用事件处理程序时:事件按DOM事件流的顺序执行事件处理程序:

父级捕获
子级冒泡
子级捕获
父级冒泡
且当事件处于目标阶段时,事件调用顺序决定于绑定事件的书写顺序,按上面的例子为,先调用冒泡阶段的事件处理程序,再调用捕获阶段的事件处理程序。依次alert出“子集冒泡”,“子集捕获”。

IE 兼容
attchEvent(‘on’ + type, handler)
detachEvent(‘on’ + type, handler)
事件是如何实现的?

在 Web 端,我们常见的就是 DOM 事件:

DOM0 级事件,直接在 html 元素上绑定 on-event,比如 onclick,取消的话,dom.onclick = null,同一个事件只能有一个处理程序,后面的会覆盖前面的。
DOM2 级事件,通过 addEventListener 注册事件,通过 removeEventListener 来删除事件,一个事件可以有多个事件处理程序,按顺序执行,捕获事件和冒泡事件
DOM3级事件,增加了事件类型,比如 UI 事件,焦点事件,鼠标事件
什么是闭包
闭包是一种特殊的对象,它由两部分组成:执行上下文(代号 A),以及在该执行上下文中创建的函数 (代号 B),当 B 执行时,如果访问了 A 中变量对象的值,那么闭包就会产生,且在 Chrome 中使用这个执行上下文 A 的函数名代指闭包

一般如何产生闭包
返回函数
函数当做参数传递
闭包的应用场景
柯里化 bind
模块
问:了解 this 嘛,bind,call,apply 具体指什么

它们都是函数的方法

call: Array.prototype.call(this, args1, args2])apply: Array.prototype.apply(this, [args1, args2]) :ES6 之前用来展开数组调用, foo.appy(null, []),ES6 之后使用 … 操作符

New 绑定时,如果是 new 一个硬绑定函数,那么会用 new 新建的对象替换这个硬绑定 this,

function foo(a) {
  this.a = a;
}

var bar = new foo(2);
console.log(bar.a)
手写 bind、apply、call
// call

Function.prototype.call = function (context, ...args) {
  context = context || window;
  
  const fnSymbol = Symbol("fn");
  context[fnSymbol] = this;
  
  context[fnSymbol](...args);
  delete context[fnSymbol];
}
// apply

Function.prototype.apply = function (context, argsArr) {
  context = context || window;
  
  const fnSymbol = Symbol("fn");
  context[fnSymbol] = this;
  
  context[fnSymbol](...argsArr);
  delete context[fnSymbol];
}
// apply

Function.prototype.apply = function (context, argsArr) {
  context = context || window;
  
  const fnSymbol = Symbol("fn");
  context[fnSymbol] = this;
  
  context[fnSymbol](...argsArr);
  delete context[fnSymbol];
}
手写题:Promise 原理

class MyPromise {
  constructor(fn) {
    this.resolvedCallbacks = [];
    this.rejectedCallbacks = [];
    
    this.state = 'PENDING';
    this.value = '';
    
    fn(this.resolve.bind(this), this.reject.bind(this));
    
  }
  
  resolve(value) {
    if (this.state === 'PENDING') {
      this.state = 'RESOLVED';
      this.value = value;
      
      this.resolvedCallbacks.map(cb => cb(value));   
    }
  }
  
  reject(value) {
    if (this.state === 'PENDING') {
      this.state = 'REJECTED';
      this.value = value;
      
      this.rejectedCallbacks.map(cb => cb(value));
    }
  }
  
  then(onFulfilled, onRejected) {
    if (this.state === 'PENDING') {
      this.resolvedCallbacks.push(onFulfilled);
      this.rejectedCallbacks.push(onRejected);
      
    }
    
    if (this.state === 'RESOLVED') {
      onFulfilled(this.value);
    }
    
    if (this.state === 'REJECTED') {
      onRejected(this.value);
    }
  }
}
      
什么是原型链?

当对象查找一个属性的时候,如果没有在自身找到,那么就会查找自身的原型,
如果原型还没有找到,那么会继续查找原型的原型,直到找到 Object.prototype 
的原型时,此时原型为 null,查找停止。这种通过 通过原型链接的逐级向上的查
找链被称为原型链

什么是原型继承?

一个对象可以使用另外一个对象的属性或者方法,就称之为继承。具体是通过
将这个对象的原型设置为另外一个对象,这样根据原型链的规则,如果查找
一个对象属性且在自身不存在时,就会查找另外一个对象,相当于一个对象
可以使用另外一个对象的属性和方法了。

数组能够调用的函数有那些?

push
pop
splice
slice
shift
unshift
sort
find
findIndex
map/filter/reduce 等函数式编程方法
还有一些原型链上的方法:toString/valudOf
如何判断数组类型

Array.isArray

PWA使用过吗?serviceWorker的使用原理是啥?

渐进式网络应用(PWA)是谷歌在2015年底提出的概念。基本上算是web应用程序,
但在外观和感觉上与原生app类似。支持PWA的网站可以提供脱机工作、
推送通知和设备硬件访问等功能。

Service Worker是浏览器在后台独立于网页运行的脚本,它打开了通向不需
要网页或用户交互的功能的大门。现在,它们已包括如推送通知和后台同
步等功能。将来,Service Worker将会支持如定期同步或地理围栏等其他功能。
本教程讨论的核心功能是拦截和处理网络请求,包括通过程序来管理缓存中的响应。
function foo(a) {
  this.a = a;
}

var bar = new foo(2);
console.log(bar.a)
手写 bind、apply、call
// call

Function.prototype.call = function (context, ...args) {
  context = context || window;
  
  const fnSymbol = Symbol("fn");
  context[fnSymbol] = this;
  
  context[fnSymbol](...args);
  delete context[fnSymbol];
}
// apply

Function.prototype.apply = function (context, argsArr) {
  context = context || window;
  
  const fnSymbol = Symbol("fn");
  context[fnSymbol] = this;
  
  context[fnSymbol](...argsArr);
  delete context[fnSymbol];
}
// apply

Function.prototype.apply = function (context, argsArr) {
  context = context || window;
  
  const fnSymbol = Symbol("fn");
  context[fnSymbol] = this;
  
  context[fnSymbol](...argsArr);
  delete context[fnSymbol];
}
手写题:Promise 原理

class MyPromise {
  constructor(fn) {
    this.resolvedCallbacks = [];
    this.rejectedCallbacks = [];
    
    this.state = 'PENDING';
    this.value = '';
    
    fn(this.resolve.bind(this), this.reject.bind(this));
    
  }
  
  resolve(value) {
    if (this.state === 'PENDING') {
      this.state = 'RESOLVED';
      this.value = value;
      
      this.resolvedCallbacks.map(cb => cb(value));   
    }
  }
  
  reject(value) {
    if (this.state === 'PENDING') {
      this.state = 'REJECTED';
      this.value = value;
      
      this.rejectedCallbacks.map(cb => cb(value));
    }
  }
  
  then(onFulfilled, onRejected) {
    if (this.state === 'PENDING') {
      this.resolvedCallbacks.push(onFulfilled);
      this.rejectedCallbacks.push(onRejected);
      
    }
    
    if (this.state === 'RESOLVED') {
      onFulfilled(this.value);
    }
    
    if (this.state === 'REJECTED') {
      onRejected(this.value);
    }
  }
}
      
什么是原型链?

当对象查找一个属性的时候,如果没有在自身找到,那么就会查找自身的原型,如果原型还没有找到,那么会继续查找原型的原型,直到找到 Object.prototype 的原型时,此时原型为 null,查找停止。这种通过 通过原型链接的逐级向上的查找链被称为原型链

什么是原型继承?

一个对象可以使用另外一个对象的属性或者方法,就称之为继承。具体是通过将这个对
象的原型设置为另外一个对象,这样根据原型链的规则,如果查找一个对象属性且在自
身不存在时,就会查找另外一个对象,相当于一个对象可以使用另外一个对象的属
性和方法了。

数组能够调用的函数有那些?

push
pop
splice
slice
shift
unshift
sort
find
findIndex
map/filter/reduce 等函数式编程方法
还有一些原型链上的方法:toString/valudOf
如何判断数组类型

Array.isArray

PWA使用过吗?serviceWorker的使用原理是啥?

渐进式网络应用(PWA)是谷歌在2015年底提出的概念。
基本上算是web应用程序,但在外观和感觉上与原生app类似。
支持PWA的网站可以提供脱机工作、推送通知和设备硬件访问等功能。

Service Worker是浏览器在后台独立于网页运行的脚本,它打开了通向
不需要网页或用户交互的功能的大门。现在,它们已包括如推送通知和
后台同步等功能。将来,Service Worker将会支持如定期同步或地理围栏
等其他功能。本教程讨论的核心功能是拦截和处理网络请求,包括通过
程序来管理缓存中的响应。
function foo() {
  return (a) => {
    console.log(this.a);
  }
}

var obj1 = {
  a: 2
}

var obj2 = {
  a: 3 
}

var bar = foo.call(obj1);
bar.call(obj2);
let 闭包

let 会产生临时性死区,在当前的执行上下文中,会进行变量提升,
但是未被初始化,
所以在执行上下文执行阶段,执行代码如果还没有执行到变量赋值,
就引用此变量就
会报错,此变量未初始化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

故事只若初见

坚持就是胜利

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值