js通过问题看本质

22 输出什么

let a = setInterval(()=>{
    console.log('hi');
},1000);
console.log(a); //1

setInterval返回唯一id,可用于clearInterval()函数清除该定时器

21 输出什么

let a = [[0,1],[2,3]].reduce((acc,cur)=>{
  return acc.concat(cur);
},[1,2]);
console.log(a); //[1, 2, 0, 1, 2, 3]

考察reduce遍历

20 js的所有内容都是原始和对象

原始类型是:boolean,null,undefined,bigint,number,string,symbol 7种

19 输出什么

(() => {
  let x, y;
  try {
    throw new Error();
  } catch (x) {
    (x = 1), (y = 2);
    console.log(x); // 1
  }
  console.log(d); // Uncaught ReferenceError: d is not defined
  console.log(x); // undefined
  console.log(y); // 2
})();

catch块接收参数x。当我们传递参数时,这与变量的x不同。这个变量x是属于catch作用域的。

之后,我们将这个块级作用域的变量设置为1,并设置变量y的值。 现在,我们打印块级作用域的变量x,它等于1。

在catch块之外,x仍然是undefined,而y是2。 当我们想在catch块之外的console.log(x)时,它返回undefined,而y返回2。

18 输出什么

const numbers = [1, 2, 3];
numbers[10] = 11;
console.log(numbers); //[1, 2, 3, empty × 7, 11]

当你为数组中的元素设置一个超过数组长度的值时,JavaScript会创建一个名为“空插槽”的东西。 这些位置的值实际上是undefined,但你会看到类似的东西:[1, 2, 3, 7 x empty, 11]

17 输出什么

console.log(typeof typeof 1); //string

typeof 1 返回 ‘number’
typeof ‘number’ 返回 ‘string’

16 判断输出false还是true

console.log(false == undefined); //false 虽然六个值都为“假”,它们之间并非都相等
console.log(false == 0); //true

console.log(Boolean(undefined)); //false
console.log(Boolean('')); //false
console.log(Boolean(' ')); //true

JavaScript中只有6个假值:

  1. undefined
  2. null
  3. NaN
  4. 0
  5. ‘’ (empty string)
  6. false

15 输出什么类型

function sayHi() {
  return (() => 0)();
}
console.log(typeof sayHi()); //number 因为0是number

只有7种内置类型:null,undefined,boolean,number,string,object和symbol。

14 单击按钮时event.target是什么

<div onclick="console.log('first div')">
   <div onclick="console.log('second div')">
     <button onclick="console.log('button')"> 
       Click!
     </button>
   </div>
</div>

event.target是button
导致事件的最深嵌套元素是事件的目标。 你可以通过event.stopPropagation停止冒泡

在事件传播期间,有三个阶段:捕获,目标和冒泡。 默认情况下,事件处理程序在冒泡阶段执行(除非您将useCapture设置为true)。 它从最深的嵌套元素向外延伸。

13 对象键自动转换为字符串

const a = {};
const b = {
  key: 'b'
};
const c = {
  key: 'c'
};

a[b] = 123;
a[c] = 456;

console.log(a); // {[object Object]: 456}
console.log(a[b]); // 456

对象键自动转换为字符串。我们试图将一个对象设置为对象a的键,其值为123。

但是,当对象自动转换为字符串化时,它变成了[Object object]。 所以我们在这里说的是a[“Object object”] = 123。 然后,我们可以尝试再次做同样的事情。 c对象同样会发生隐式类型转换。那么,a[“Object object”] = 456。

然后,我们打印a[b],它实际上是a[“Object object”]。 我们将其设置为456,因此返回456。

12 考察Browser 对象的存储对象保存多久

sessionStorage.setItem(‘cool_secret’,123); //关闭选项卡后就会丢失数据

11 输出什么,考察基础-全局函数

const sum = eval('10*10+5');
console.log(sum); //105

eval为全局函数,eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行。

10 输出什么

function getAge() {
  'use strict';
  age = 21;
  console.log(age); //Uncaught ReferenceError: age is not defined
}

getAge();

使用“use strict”,可以确保不会意外地声明全局变量。 我们从未声明变量age,因为我们使用`use strict’,它会引发一个ReferenceError。 如果我们不使用“use strict”,它就会起作用,因为属性age会被添加到全局对象中。

ReferenceError(引用错误) 对象代表当一个不存在的变量被引用时发生的错误。

9 比较

function checkAge(data) {
  if (data === {
      age: 18
    }) {
    console.log("You are an adult!");
  } else if (data == {
      age: 18
    }) {
    console.log("You are still an adult.");
  } else {
    console.log(`Hmm.. You don't have an age I guess`);
  }
}

checkAge({
  age: 18
}); //Hmm.. You don't have an age I guess

在比较相等性,原始类型通过它们的值进行比较,而对象通过它们的引用进行比较。JavaScript检查对象是否具有对内存中相同位置的引用。

我们作为参数传递的对象和我们用于检查相等性的对象在内存中位于不同位置,所以它们的引用是不同的。

这就是为什么{ age: 18 } === { age: 18 }和 { age: 18 } == { age: 18 } 返回 false的原因。

8 输出什么

function getPersonInfo(one, two, three) {
  console.log(one); //["", " is ", " years old", raw: Array(3)]
  console.log(two); //Lydia
  console.log(three); //21
}

const person = 'Lydia';
const age = 21;

getPersonInfo `${person} is ${age} years old`;

如果使用标记的模板字符串,则第一个参数的值始终是字符串值的数组。 其余参数获取传递到模板字符串中的表达式的值!

7 所有对象都有原型?

错误

除基础对象外,所有对象都有原型。 基础对象可以访问某些方法和属性,例如.toString。 这就是您可以使用内置JavaScript方法的原因! 所有这些方法都可以在原型上找到。 虽然JavaScript无法直接在您的对象上找到它,但它会沿着原型链向下寻找并在那里找到它,这使您可以访问它。

基础对象指原型链终点的对象。基础对象的原型是null。

console.log(Object.prototype.__proto__); // null

6 输出什么

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

const lydia = new Person("Lydia", "Hallie");
const sarah = Person("Sarah", "Smith");

console.log(lydia); // Person {firstName: "Lydia", lastName: "Hallie"}
console.log(sarah); // undefined
console.log(firstName); // Sarah
console.log(lastName); // Smith

对于sarah,我们没有使用new关键字。 使用new时,它指的是我们创建的新空对象。 但是,如果你不添加new它(this)指的是全局对象!

我们指定了this.firstName等于’Sarah和this.lastName等于Smith。 我们实际做的是定义global.firstName ='Sarah’和global.lastName ='Smith。 sarah本身的返回值是undefined。

5 输出什么

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

const member = new Person("Lydia", "Hallie");
Person.getFullName = () => this.firstName + this.lastName;

console.log(member.getFullName()); //TypeError

不能像使用常规对象那样向构造函数添加属性。 如果要一次向所有对象添加功能,则必须使用原型。js的强制规定,因为不是每个实例都要用到加到构造函数的方法,要用就加在构造函数方法的原型上继承

4 是否可操作

function bark() {
  console.log('Woof!');
}
bark.animal = 'dog';
console.log(bark.animal); // dog

可操作,函数是一种特殊类型的对象。您自己编写的代码并不是实际的函数。 该函数是具有属性的对象,此属性是可调用的。

3 为什么报异常

class Chameleon {
  static colorChange(newColor) {
    this.newColor = newColor;
  }

  constructor({
    newColor = 'green'
  } = {}) {
    this.newColor = newColor;
  }
}

const freddie = new Chameleon({
  newColor: 'purple'
});
freddie.colorChange('orange'); // TypeError

colorChange方法是静态的。 静态方法仅在创建它们的构造函数中存在,并且不能传递给任何子级。 由于freddie是一个子级对象,函数不会传递,所以在freddie实例上不存在freddie方法:抛出TypeError。

2 输出什么以及为什么

for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i) //3 3 3
  }, 1);
}

for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i) //0 1 2
  }, 1);
}

由于JavaScript中的事件执行机制,setTimeout函数真正被执行时,循环已经走完。 由于第一个循环中的变量i是使用var关键字声明的,因此该值是全局的。 在循环期间,我们每次使用一元运算符++都会将i的值增加1。 因此在第一个例子中,当调用setTimeout函数时,i已经被赋值为3。

在第二个循环中,使用let关键字声明变量i:使用let(和const)关键字声明的变量是具有块作用域的(块是{}之间的任何东西)。 在每次迭代期间,i将被创建为一个新值,并且每个值都会存在于循环内的块级作用域。

JavaScript中的事件执行机制(事件循环(event loop)):

  1. javascript是一门单线程语言,一切javascript版的"多线程"都是用单线程模拟出来的。
  2. 所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
  3. JavaScript除了广义上的的同步任务何异步任务,其对任务还有更精细的定义:1 macro-task(宏任务):包括整体代码script,setTimeout,setInterval 2 micro-task(微任务):Promise,process.nextTick 不同类型的任务会进入对应的Event Queue。
  4. 事件循环的顺序,决定js代码的执行顺序。进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。
  5. 以同步异步的方式来解释执行机制是不准确的,更加准确的方式是宏任务和微任务:在一个事件循环中,执行第一个宏任务,宏任务执行结束,执行当前事件循环中的微任务,执行完毕之后进入下一个事件循环中,或者说执行下一个宏任务

JavaScript执行机制

1 name和age输出什么? - 考验变量提升

function sayHi() {
  console.log(name); //undefined
  console.log(age); //ReferenceError(引用错误) 对象代表当一个不存在的变量被引用时发生的错误。
  var name = 'Lydia';
  let age = 21;
}
sayHi();

在函数中,我们首先使用var关键字声明了name变量。 这意味着变量在创建阶段会被提升(JavaScript会在创建变量创建阶段为其分配内存空间),默认值为undefined,直到我们实际执行到使用该变量的行。 我们还没有为name变量赋值,所以它仍然保持undefined的值。

使用let关键字(和const)声明的变量也会存在变量提升,但与var不同,初始化没有被提升。 在我们声明(初始化)它们之前,它们是不可访问的。 这被称为“暂时死区”。 当我们在声明变量之前尝试访问变量时,JavaScript会抛出一个ReferenceError。

let 的「创建」过程被提升了,但是初始化没有提升。

var 的「创建」和「初始化」都被提升了。

function 的「创建」「初始化」和「赋值」都被提升了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值