不知道是什么东西

new操作符的实现原理

  1. 首先创建了一个新的空对象
  2. 设置原型,将对象的原型设置为函数的 prototype 对象。
  3. 让函数的 this 指向这个对象,执行构造函数的代码(为这个新对象添加属性)
  4. 判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。
function objectFactory() {
  let newObject = null;
  let constructor = Array.prototype.shift.call(arguments);
  let result = null;
  // 判断参数是否是一个函数
  if (typeof constructor !== "function") {
    console.error("type error");
    return;
  }
  // 新建一个空对象,对象的原型为构造函数的 prototype 对象
  newObject = Object.create(constructor.prototype);
  // 将 this 指向新建对象,并执行函数
  result = constructor.apply(newObject, arguments);
  // 判断返回对象
  let flag = result && (typeof result === "object" || typeof result === "function");
  // 判断返回结果
  return flag ? result : newObject;
}

// 使用方法
objectFactory(构造函数, 初始化参数);

map和weakMap的区别???

JavaScript 类数组对象的定义?

  一个拥有 length 属性和若干索引属性的对象就可以被称为类数组对象,类数组对象和数组类似,但是不能调用数组的方法。常见的类数组对象有 arguments 和 DOM 方法的返回结果。

  arguments 是一个对象,它的属性是从 0 开始依次递增的数字,还有length等属性,与数组相似;但是它却没有数组常见的方法属性,如forEach, reduce等,所以叫它们类数组。

类数组转换为数组的方法:

  1. Array.from(arrayLike);
  2. Array.prototype.slice.call(arrayLike);
  3. Array.prototype.splice.call(arrayLike, 0);
  4. Array.prototype.concat.apply([], arrayLike);

遍历类数组的方法:

// 可以使用call和apply方法
function foo(){ 
  Array.prototype.forEach.call(arguments, a => console.log(a))
}

// Array.from方法将类数组转化成数组
function foo(){ 
  const arrArgs = Array.from(arguments) 
  arrArgs.forEach(a => console.log(a))
}

// 展开运算符将类数组转化成数组
function foo(){ 
    const arrArgs = [...arguments] 
    arrArgs.forEach(a => console.log(a)) 
}

 

数组的原生:

  1. 转换为字符串:toString()、toLocalString()、join()
  2. 数组尾部操作的方法 pop() 和 push()。
  3. 数组首部操作的方法 shift() 和 unshift()
  4. 数组连接的方法 concat() ,返回的是拼接好的数组,不影响原数组。
  5. 数组截取办法 slice(),用于截取数组中的一部分返回,不影响原数组。
  6. 数组插入方法 splice(),影响原数组查找特定项的索引的方法
  7. indexOf() 和 lastIndexOf()
  8. 迭代方法 every()、some()、filter()、map() 和 forEach() 方法
  9. 数组归并方法 reduce()

什么是 DOM 和 BOM?

  DOM: 指的是文档对象模型,是把文档当做一个对象,这个对象主要定义了处理网页内容的方法和接口。

  BOM: 指的是浏览器对象模型,是把浏览器当做一个对象来对待,这个对象主要定义了与浏览器进行交互的方法和接口。BOM的核心是 windowwindow 对象含有 location 对象、navigator 对象、screen 对象等子对象,并且 DOM 的最根本的对象 document 对象也是 BOM 的 window 对象的子对象

escape、encodeURI、encodeURIComponent 的区别

  encodeURI: 是对整个 URI 进行转义,将 URI 中的非法字符转换合法字符,所以对于一些在 URI 中有特殊意义的字符不会进行转义。

  encodeURIComponent: 是对 URI 的组成部分进行转义,所以一些特殊字符也会得到转义。

  escape 和 encodeURI: 的作用相同,不过它们对于 unicode 编码为 0xff 之外字符的时候会有区别,escape 是直接在字符的 unicode 编码前加上 %u,而 encodeURI 首先会将字符转换为 UTF-8 的格式,再在每个字节前加上 %。

AJAX的理解,实现一个AJAX请求

  AJAX 指的是通过 JavaScript 的 异步通信,从服务器获取 XML 文档从中提取数据,再更新当前网页的对应部分,而不用刷新整个网页。

  创建AJAX请求的步骤:

  1. 创建一个 XMLHttpRequest 对象。
  2. 在这个对象上使用 open 方法创建一个 HTTP 请求
  3. 添加请求头状态监听方法 , XMLHttpRequest 对象一共有 5 个状态,当它的状态变化时会触发onreadystatechange 事件
  4. send 请求
const SERVER_URL = "/server";
let xhr = new XMLHttpRequest();
// 创建 Http 请求
xhr.open("GET", url, true);
// 设置状态监听函数
xhr.onreadystatechange = function() {
  if (this.readyState !== 4) return;
  // 当请求成功时
  if (this.status === 200) {
    handle(this.response);
  } else {
    console.error(this.statusText);
  }
};
// 设置请求失败时的监听函数
xhr.onerror = function() {
  console.error(this.statusText);
};
// 设置请求头信息
xhr.responseType = "json";
xhr.setRequestHeader("Accept", "application/json");
// 发送 Http 请求
xhr.send(null);

使用Promise封装AJAX:

// promise 封装实现:
function getJSON(url) {
  // 创建一个 promise 对象
  let promise = new Promise(function(resolve, reject) {
    let xhr = new XMLHttpRequest();
    // 新建一个 http 请求
    xhr.open("GET", url, true);
    // 设置状态的监听函数
    xhr.onreadystatechange = function() {
      if (this.readyState !== 4) return;
      // 当请求成功或失败时,改变 promise 的状态
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
    // 设置错误监听函数
    xhr.onerror = function() {
      reject(new Error(this.statusText));
    };
    // 设置响应的数据类型
    xhr.responseType = "json";
    // 设置请求头信息
    xhr.setRequestHeader("Accept", "application/json");
    // 发送 http 请求
    xhr.send(null);
  });
  return promise;
}

 

JavaScript为什么要进行变量提升,有什么问题?

  变量提升的表现是,无论在函数中何处位置声明的变量,好像都被提升到了函数的首部,可以在变量声明前访问到而不会报错。

  造成变量声明提升的本质原因js 引擎在代码执行前有一个解析的过程,创建了执行上下文,初始化了一些代码执行时需要用到的对象。当访问一个变量时,会到当前执行上下文中的作用域链中去查找

  首先要知道,JS在拿到一个变量或者一个函数的时候,会有两步操作,即解析执行

  解析: JS会检查语法,并对函数进行预编译。解析的时候会先创建一个全局执行上下文环境,先把代码中即将执行的变量、函数声明都拿出来,变量先赋值为undefined,函数先声明好可使用。在一个函数执行之前,也会创建一个函数执行上下文环境,跟全局执行上下文类似,不过函数执行上下文会多出this、arguments和函数的参数。

  执行: 就是按照代码的顺序依次执行。

  变量提升的两个原因提高性能 容错性更好

ES6模块与CommonJS模块有什么异同?

  CommonJS 是社区规范, ES6 Module 是官方后出的规范

  1. CommonJS 模块输出的是一个值的拷贝,ES6 Module 输出的是值的引用
  2. CommonJS 模块是运行时加载,ES6 Module 是编译时输出接口。
  3. CommonJS 是单个值导出,ES6 Module可以导出多个
  4. CommonJS 是动态语法可以写在判断里,ES6 Module 静态语法只能写在顶层
  5. CommonJS 的 this 是当前模块,ES6 Module 的 this 是 undefined
 

React的 setState 同步还是异步

  setState 本身代码的执行肯定是同步的,这里的异步是指是多个 state 会合成到一起进行批量更新。 同步还是异步取决于它被调用的环境。

  • 如果 setState 在 React 能够控制的范围被调用,它就是异步的。比如合成事件处理函数,生命周期函数, 此时会进行批量更新,也就是将状态合并后再进行 DOM 更新。
  • 如果 setState 在原生 JavaScript 控制的范围被调用,它就是同步的。比如原生事件处理函数,定时器回调函数,Ajax 回调函数中,此时 setState 被调用后会立即更新 DOM 。

对函数式编程的理解

简明 JavaScript 函数式编程——入门篇

函数式编程有两个核心概念

  • 数据不可变(无副作用): 它要求你所有的数据都是不可变的,这意味着如果你想修改一个对象,那你应该创建一个新的对象用来修改,而不是修改已有的对象。
  • 无状态: 主要是强调对于一个函数,不管你何时运行,它都应该像第一次运行一样,给定相同的输入,给出相同的输出,完全不依赖外部状态的变化。

纯函数带来的意义

  • 便于测试和优化:这个意义在实际项目开发中意义非常大,由于纯函数对于相同的输入永远会返回相同的结果,因此我们可以轻松断言函数的执行结果,同时也可以保证函数的优化不会影响其他代码的执行。
  • 可缓存性:因为相同的输入总是可以返回相同的输出,因此,我们可以提前缓存函数的执行结果。
  • 更少的 Bug:使用纯函数意味着你的函数中不存在指向不明的 this,不存在对全局变量的引用,不存在对参数的修改,这些共享状态往往是绝大多数 bug 的源头。
posted @ 2022-05-10 20:35  夏目友人喵  阅读(97)  评论(0编辑  收藏  举报