javascript-----与原生js相关的重要整理,原生基础

1. typeof 是否正确判断类型? instanceof 呢? instanceof 的实现原理是什么?
typeof 能够正确的判断基本数据类型,但是除了 null, typeof null 输出的是对象。
对于对象来说,typeof 不能正确的判断其类型, typeof 一个函数可以输出 ‘function’, 而除此之外,输出的全是 object。
instanceof 可以准确的判断复杂数据类型,但是不能正确判断基本数据类型。
instanceof 是通过原型链判断的,A instanceof B, 在 A 的原型链中层层查找,是否有原型等于 B.prototype,如果一直找到 A 的原型链的顶端 (null; 即Object.prototype.proto), 仍然不等于 B.prototype,那么返回 false,否则返回 true。

// L instanceof R
function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
    var O = R.prototype;// 取 R 的显式原型
    L = L.__proto__;    // 取 L 的隐式原型
    while (true) {
        if (L === null) // 已经找到顶层
            return false;
        if (O === L)   // 当 O 严格等于 L 时,返回 true
            return true;
        L = L.__proto__;  // 继续向上一层原型链查找
    }
}

2.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: 只能遍历数组,不能中断,返回值是修改后的数组。
3 . 如何判断一个变量是不是数组?
使用 Array.isArray 判断,如果返回 true, 说明是数组;
使用 instanceof Array 判断,如果返回 true, 说明是数组;
使用 Object.prototype.toString.call 判断,如果值是 [object Array], 说明是数组;
通过 constructor 来判断,如果是数组,那么 arr.constructor === Array. (不准确,因为我们可以指定 obj.constructor = Array)。
4. 类数组和数组的区别是什么?
1)拥有 length 属性,其它属性(索引)为非负整数(对象中的索引会被当做字符串来处理);
2)不具有数组所具有的方法;
类数组是一个普通对象,而真实的数组是 Array 类型。
常见的类数组有: 函数的参数 arugments, DOM 对象列表 (比如通过 document.querySelectorAll 得到的列表), jQuery 对象 (比如 $(“div”))。
类数组可以转换为数组:

// 第一种方法
Array.prototype.slice.call(arrayLike, start);
// 第二种方法
[...arrayLike];
// 第三种方法:
//Array.from 方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象。
Array.from(arrayLike);

5.思考: [] == ![]

[] == ![]
//true

! 优先级是高于 ==

![]  //false

一方是 boolean,将 boolean 转为 number 再进行判断,false 转换成 number,对应的值是 0.
一方是number,那么将 object 也转换成 Number, 空数组转换成数字,对应的值是 0.(空数组转换成数字,对应的值是 0,如果数组中只有一个数字,那么转成 number 就是这个数字,其它情况,均为 NaN)
在这里插入图片描述
6.在 JS 中什么是变量提升?什么是暂时性死区?
变量提升就是变量在声明之前就可以使用,值为 undefined。
在代码块内,使用 let/const 命令声明变量之前,该变量都是不可用的 (会抛出错误)。这在语法上,称为“暂时性死区”。

typeof x; // ReferenceError(暂时性死区,抛错)
let x;

typeof y; // 值是 undefined, 不会报错

暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
7.词法作用域和 this 的区别
词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的;
this 是在调用时被绑定的,this 指向什么,完全取决于函数的调用位置 (关于 this 的指向问题,本文已经有说明)。
8.谈谈你对 JS 执行上下文栈和作用域链的理解。
执行上下文就是当前 JavaScript 代码被解析和执行时所在环境, JS 执行上下文栈可以认为是一个存储函数调用的栈结构,遵循先进后出的原则。
作用域链: 无论是 LHS 还是 RHS 查询,都会在当前的作用域开始查找,如果没有找到,就会向上级作用域继续查找目标标识符,每次上升一个作用域,一直到全局作用域为止。
9.new 的原理是什么?通过 new 的方式创建对象和通过字面量创建有什么区别?
new
创建一个新对象;
这个新对象会被执行 [[原型]] 连接;
将构造函数的作用域赋值给新对象,即 this 指向这个新对象;
如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象。

function new(fn, ...args) {
// 创建一个对象
  const obj = {}

  // 让该对象可以访问构造函数原型链上的属性
  obj.__proto__ = fn.prototype;

  // 获取构造函数运行返回的结果
  let res = fn.apply(obj, args)

  // 当res为引用类型(复杂对象)则直接返回该结果; 否则返回obj,也就是构造函数中的this
  return typeof res === 'object' ? res || obj : obj
}

通过对象字面量定义对象时,不会调用 Object 构造函数。
10.谈谈你对原型的理解?
在 JavaScript 中,每当定义一个对象(函数也是对象)时候,对象中都会包含一些预定义的属性。其中每个函数对象都有一个 prototype 属性,这个属性指向函数的原型对象。使用原型对象的好处是所有对象实例共享它所包含的属性和方法。
11. 什么是原型链?【原型链解决的是什么问题?】
原型链解决的主要是继承问题。
每个对象拥有一个原型对象,通过 proto 指针指向其原型对象,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向 null(Object.proptotype.proto 指向的是 null)。这种关系被称为原型链 (prototype chain),通过原型链一个对象可以拥有定义在其他对象中的属性和方法。
在这里插入图片描述
12.prototype 和 proto 区别是什么?
prototype 是构造函数的属性。

__proto__ 是每个实例都有的属性,可以访问 [[prototype]] 属性。
实例的__proto__ 与其构造函数的 prototype 指向的是同一个对象。

13. 取数组的最大值(ES5、ES6)

// ES5 的写法
Math.max.apply(null, [14, 3, 77, 30]);

// ES6 的写法
Math.max(...[14, 3, 77, 30]);

// reduce
[14,3,77,30].reduce((accumulator, currentValue)=>{
    return accumulator = accumulator > currentValue ? accumulator : currentValue
});

14.Promise 和 setTimeout 的区别 ?
Promise 的构造函数是同步执行的。then 是异步执行的。
Promise 是微任务,setTimeout 是宏任务,同一个事件循环中,promise.then 总是先于 setTimeout 执行。
15.什么是函数柯里化?实现 sum(1)(2)(3) 返回结果是 1,2,3 之和
函数柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

function sum(a) {
    return function(b) {
        return function(c) {
            return a+b+c;
        }
    }
}
console.log(sum(1)(2)(3)); // 6

将一个普通函数柯里化

function curry(fn, args = []) {
    return function(){
        let rest = [...args, ...arguments];
        if (rest.length < fn.length) {
            return curry.call(this,fn,rest);
        }else{
            return fn.apply(this,rest);
        }
    }
}
//test
function sum(a,b,c) {
    return a+b+c;
}
let sumFn = curry(sum);
console.log(sumFn(1)(2)(3)); //6
console.log(sumFn(1)(2, 3)); //6
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值