06月24, 2022

六、JavaScript 面试题汇总(251-301)

251. 下面代码的输出是什么?( D

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

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

const freddie = new Chameleon({ newColor: "purple" });
freddie.colorChange("orange");
  • A: orange
  • B: purple
  • C: green
  • D: TypeError

分析

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

252. 下面代码的输出是什么?( A

let greeting;
greetign = {}; // Typo!
console.log(greetign);
  • A: {}
  • B: ReferenceError: greetign is not defined
  • C: undefined

分析:

控制台会输出空对象,因为我们刚刚在全局对象上创建了一个空对象!

当我们错误地将 greeting 输入为 greetign 时,JS 解释器实际上在浏览器中将其视为 window.greetign = {}

253. 当我们执行以下代码时会发生什么?( A

function bark() {
  console.log("Woof!");
}

bark.animal = "dog";
  • A 什么都不会发生
  • B: SyntaxError. You cannot add properties to a function this way.
  • C: undefined
  • D: ReferenceError

    分析:

    因为函数也是对象!(原始类型之外的所有东西都是对象)

    函数是一种特殊类型的对象,我们可以给函数添加属性,且此属性是可调用的。

254. 下面代码的输出是什么?( A

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());
  • A: TypeError
  • B: SyntaxError
  • C: Lydia Hallie
  • D: undefined undefined

分析:

Person.getFullName 是将方法添加到了函数身上,因此当我们通过实例对象 member 去调用该方法时并不能找到该方法。

255. 下面代码的输出是什么?( A

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

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

console.log(lydia);
console.log(sarah);
  • A: Person { firstName: "Lydia", lastName: "Hallie" }undefined
  • B: Person { firstName: "Lydia", lastName: "Hallie" }Person { firstName: "Sarah", lastName: "Smith" }
  • C: Person { firstName: "Lydia", lastName: "Hallie" }{}
  • D: Person { firstName: "Lydia", lastName: "Hallie" }ReferenceError

分析:

lydia 是调用构造函数后得到的实例对象,拥有 firstNamelastName 属性;

sarah 是调用普通函数后得到的返回值,而 Person 作为普通函数没有返回值;

256. 事件传播的三个阶段是什么?( D

  • A: 目标 > 捕获 > 冒泡
  • B: 冒泡 > 目标 > 捕获
  • C: 目标 > 冒泡 > 捕获
  • D: 捕获 > 目标 > 冒泡

257. 下面代码的输出是什么?( C

function sum(a, b) {
  return a + b;
}

sum(1, "2");
  • A: NaN
  • B: TypeError
  • C: "12"
  • D: 3

分析:

任意数据类型在跟 String 做 + 运算时,都会隐式转换为 String 类型。

a 所对应的 Number1,被隐式转换为了 String 值 "1",最终字符串拼接的到 "12"。

258. 下面代码的输出是什么?( C

let number = 0;
console.log(number++);
console.log(++number);
console.log(number);
  • A: 1 1 2
  • B: 1 2 2
  • C: 0 2 2
  • D: 0 1 2

分析:

++ 后置时,先输出,后加 1;++ 前置时,先加 1,后输出;

第一次输出的值为 0,输出完成后 number1 变为 1

第二次输出,number 先加 1 变为 2,然后输出值 2

第三次输出,number 值没有变化,还是 2

259. 下面代码的输出是什么?( B

function getPersonInfo(one, two, three) {
  console.log(one);
  console.log(two);
  console.log(three);
}

const person = "Lydia";
const age = 21;

getPersonInfo`${person} is ${age} years old`;
  • A: Lydia 21 ["", "is", "years old"]
  • B: ["", "is", "years old"] Lydia 21
  • C: Lydia ["", "is", "years old"] 21

分析:

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

260. 下面代码的输出是什么?( C

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 });
  • A: You are an adult!
  • B: You are still an adult.
  • C: Hmm.. You don't have an age I guess

分析:

在比较相等性时,原始类型通过它们的值进行比较,而对象通过它们的引用进行比较。

data 和条件中的 { age: 18 } 两个不同引用的对象,因此永远都不相等。

261. 下面代码的输出是什么?( C

function getAge(...args) {
  console.log(typeof args);
}

getAge(21);
  • A: "number"
  • B: "array"
  • C: "object"
  • D: "NaN"

分析:

ES6 中的不定参数(…args)返回的是一个数组。

typeof 检查数组的类型返回的值是 object

262. 下面代码的输出是什么?( C

function getAge() {
  "use strict";
  age = 21;
  console.log(age);
}

getAge();
  • A: 21
  • B: undefined
  • C: ReferenceError
  • D: TypeError

分析:

"use strict" 严格模式中,使用未声明的变量会引发报错。

263. 下面代码的输出是什么?( A

const sum = eval("10*10+5");
  • A: 105
  • B: "105"
  • C: TypeError
  • D: "10\10+5"*

分析:

eval 方法会将字符串当作 JavaScript 代码进行解析。

264. cool_secret 可以访问多长时间?( B

sessionStorage.setItem("cool_secret", 123);
  • A:永远,数据不会丢失。
  • B:用户关闭选项卡时。
  • C:当用户关闭整个浏览器时,不仅是选项卡。
  • D:用户关闭计算机时。

分析:

sessionStorage 是会话级别的本地存储,当窗口关闭,则会话结束,数据删除。

265. 下面代码的输出是什么?( B

var num = 8;
var num = 10;

console.log(num);
  • A: 8
  • B: 10
  • C: SyntaxError
  • D: ReferenceError

分析:

var 声明的变量允许重复声明,但后面的值会覆盖前面的值。

266. 下面代码的输出是什么?( C

const obj = { 1: "a", 2: "b", 3: "c" };
const set = new Set([1, 2, 3, 4, 5]);

obj.hasOwnProperty("1");
obj.hasOwnProperty(1);
set.has("1");
set.has(1);
  • A: false true false true
  • B: false true true true
  • C: true true false true
  • D: true true true true

267. 下面代码的输出是什么?( C

const obj = { a: "one", b: "two", a: "three" };
console.log(obj);
  • A: { a: "one", b: "two" }
  • B: { b: "two", a: "three" }
  • C: { a: "three", b: "two" }
  • D: SyntaxError

分析:

如果对象有两个具有相同名称的键,则后面的将替前面的键。它仍将处于第一个位置,但具有最后指定的值。

268. 下面代码的输出是什么?( C

for (let i = 1; i < 5; i++) {
  if (i === 3) continue;
  console.log(i);
}
  • A: 1 2
  • B: 1 2 3
  • C: 1 2 4
  • D: 1 3 4

分析:

i 的值为 3 时,进入 if 语句执行 continue,结束本次循环,立即进行下一次循环。

269. 下面代码的输出是什么?( A

String.prototype.giveLydiaPizza = () => {
  return "Just give Lydia pizza already!";
};

const name = "Lydia";

name.giveLydiaPizza();
  • A: "Just give Lydia pizza already!"
  • B: TypeError: not a function
  • C: SyntaxError
  • D: undefined

分析:

String 是一个内置的构造函数,我们可以为它添加属性。 我们给它的原型添加了一个方法。 原始类型的字符串自动转换为字符串对象,由字符串原型函数生成。 因此,所有字符串(字符串对象)都可以访问该方法!

当使用基本类型的字符串调用 giveLydiaPizza 时,实际上发生了下面的过程:

  • 创建一个 String 的包装类型实例
  • 在实例上调用 substring 方法
  • 销毁实例

270. 下面代码的输出是什么?( B

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

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

console.log(a[b]);
  • A: 123
  • B: 456
  • C: undefined
  • D: ReferenceError

分析:

bc 作为一个对象的键时,会自动转换为字符串,而对象自动转换为字符串化时,结果都为 [Object object]。因此 a[b]a[c] 其实都是同一个属性 a["Object object"]

对象同名的属性后面的值会覆盖前面的,因此最终 a["Object object"] 的值为 456

271. 下面代码的输出是什么?( B

const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"));
const baz = () => console.log("Third");

bar();
foo();
baz();
  • A: First Second Third
  • B: First Third Second
  • C: Second First Third
  • D: Second Third First

分析:

bar 函数中执行的是一段异步代码,按照 JavaScript 中的事件循环机制,主线程中的所有同步代码执行完成后才会执行异步代码。因此 "Second" 最后输出。

272. 单击按钮时 event.target 是什么?( C

<div onclick="console.log('first div')">
  <div onclick="console.log('second div')">
    <button onclick="console.log('button')">
      Click!
    </button>
  </div>
</div>
  • A: div 外部
  • B: div 内部
  • C: button
  • D: 所有嵌套元素的数组

分析:

event.target 指向的是事件目标,即触发事件的元素。因此点击 \

273. 单击下面的 html 片段打印的内容是什么?( A

<div onclick="console.log('div')">
  <p onclick="console.log('p')">
    Click here!
  </p>
</div>
  • A: p div
  • B: div p
  • C: p
  • D: div

分析:

onclick 绑定的事件为冒泡型事件。因此当点击 p 标签时,事件会从事件目标开始依次往外触发。

274. 下面代码的输出是什么?( D

const person = { name: "Lydia" };

function sayHi(age) {
  console.log(`${this.name} is ${age}`);
}

sayHi.call(person, 21);
sayHi.bind(person, 21);
  • A: undefined is 21 Lydia is 21
  • B: function function
  • C: Lydia is 21 Lydia is 21
  • D: Lydia is 21 function

分析:

callbind 都可以修改 this 的指向,但区别在于 call 方法会立即执行,而 bind 会返回一个修改后的新函数。

275. 下面代码的输出是什么?( B

function sayHi() {
  return (() => 0)();
}

typeof sayHi();
  • A: "object"
  • B: "number"
  • C: "function"
  • D: "undefined"

分析:

return 后是一个 IIFE,其返回值是 0,因此 sayHi 函数中返回的是一个 0typeof 检测 sayHi 返回值类型即为 number

276. 下面这些值哪些是假值?( A

0;
new Number(0);
("");
(" ");
new Boolean(false);
undefined;
  • A: 0 "" undefined
  • B: 0 new Number(0) "" new Boolean(false) undefined
  • C: 0 "" new Boolean(false) undefined
  • D: 所有都是假值。

分析:

JavaScript 中假值只有 6 个:false""nullundefinedNaN0

278. 下面代码的输出是什么?( B

console.log(typeof typeof 1);
  • A: "number"
  • B: "string"
  • C: "object"
  • D: "undefined"

分析:

typeof 1 返回 "number"typeof "number" 返回 "string"

279. 下面代码的输出是什么?( C

const numbers = [1, 2, 3];
numbers[10] = 11;
console.log(numbers);
  • A: [1, 2, 3, 7 x null, 11]
  • B: [1, 2, 3, 11]
  • C: [1, 2, 3, 7 x empty, 11]
  • D: SyntaxError

分析:

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

[1, 2, 3, 7 x empty, 11]

这取决于你运行它的位置(每个浏览器有可能不同)。

280. 下面代码的输出是什么?( A

(() => {
  let x, y;
  try {
    throw new Error();
  } catch (x) {
    (x = 1), (y = 2);
    console.log(x);
  }
  console.log(x);
  console.log(y);
})();
  • A: 1 undefined 2
  • B: undefined undefined undefined
  • C: 1 1 2
  • D: 1 undefined undefined

分析:

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

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

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

281. JavaScript 中的所有内容都是…( A

  • A:原始或对象
  • B:函数或对象
  • C:技巧问题!只有对象
  • D:数字或对象

分析:

JavaScript 只有原始类型和对象。

282. 下面代码的输出是什么?

[[0, 1], [2, 3]].reduce(
  (acc, cur) => {
    return acc.concat(cur);
  },
  [1, 2]
);
  • A: [0, 1, 2, 3, 1, 2]
  • B: [6, 1, 2]
  • C: [1, 2, 0, 1, 2, 3]
  • D: [1, 2, 6]

分析:

[1,2] 是我们的初始值。 这是我们开始执行 reduce 函数的初始值,以及第一个 acc 的值。 在第一轮中,acc[1,2]cur[0,1]。 我们将它们连接起来,结果是 [1,2,0,1]

然后,acc 的值为 [1,2,0,1]cur 的值为 [2,3]。 我们将它们连接起来,得到 [1,2,0,1,2,3]

283. 下面代码的输出是什么?( B

!!null;
!!"";
!!1;
  • A: false true false
  • B: false false true
  • C: false true true
  • D: true true false

分析:

null 是假值。 !null 返回 true!true 返回 false

"" 是假值。 !"" 返回 true!true 返回 false

1 是真值。 !1 返回 false!false 返回 true

284. setInterval 方法的返回值什么?( A

setInterval(() => console.log("Hi"), 1000);
  • A:一个唯一的 id
  • B:指定的毫秒数
  • C:传递的函数
  • D:undefined

分析:

它返回一个唯一的 id。 此 id 可用于使用 clearInterval() 函数清除该定时器。

285. 下面代码的返回值是什么?( A

[..."Lydia"];
  • A: ["L", "y", "d", "i", "a"]
  • B: ["Lydia"]
  • C: [[], "Lydia"]
  • D: [["L", "y", "d", "i", "a"]]

分析:

字符串是可迭代的。 扩展运算符将迭代的每个字符映射到一个元素。

286. document.writeinnerHTML 有哪些区别?

参考答案:

document.writeinnerHTML 都能将 HTML 字符串解析为 DOM 树,再将 DOM 树插入到某个位置,但两种在执行细节上还是有许多不同。

1)write() 方法存在于 Document 对象中,innerHTML 属性存在于 Element 对象中;

2)document.write 会将解析后的 DOM 树插入到文档中调用它的脚本元素的位置,而 innerHTML 会将 DOM 树插入到指定的元素内;

3)document.write 会将多次调用的字符串参数自动连接起来,innerHTML 要用赋值运算符 "+=" 拼接;

4)只有当文档还在解析时,才能使用 document.write,否则 document.write 的值会将当前文档覆盖掉,而 innerHTML 属性则没有这个限制;

注:也可以参阅前面第 157 题答案

287. 假设有两个变量 ab,他们的值都是数字,如何在不借用第三个变量的情况下,将两个变量的值对调?

参考答案:

方法一:

a = a + b;
b = a - b;
a = a - b;

方法二(ES6 中的解构):

[a, b] = [b, a]

288. 前端为什么提倡模块化开发?

参考答案:

模块化能将一个复杂的大型系统分解成一个个高内聚、低耦合的简单模块,并且每个模块都是独立的,用于完成特定的功能。模块化后的系统变得更加可控、可维护、可扩展,程序代码也更简单直观,可读性也很高,有利于团队协作开发。ES6 模块化的出现,使得前端能更容易、更快速的实现模块化开发。

289. 请解释 JSONP 的原理,并用代码描述其过程。

参考答案:

JSONP(JSON with padding) 是一种借助 <script>元素实现跨域的技术,它不会使用 XHR 对象。之所以能实现跨域,主要是因为 <script> 元素有以下两个特点:

1)它的 src 属性能够访问任何 URL 资源,不会受同源策略的限制;

2)如果访问的资源包含 JavaScript 代码,那么在下载下来后会自动执行;

JSONP 就是基于这两点,再与服务器配合来实现跨域请求的,它的执行步骤可分为以下 6 步:

1)定义一个回调函数;

2)用 DOM 方法动态创建一个 <script> 元素;

3)通过 <script> 元素的 src 属性指定要请求的 URL,并且将回调函数的名称作为一个参数传递过去;

4)将 <script> 元素插入到当前文档中,开始请求;

5)服务器接收到传递过来的参数,然后将回调函数和数据以调用的形式输出;

6)当 <script> 元素接收到响应中的脚本代码后,就会自动的执行它们;

290. 列举几种 JavaScript 中数据类型的强制转换和隐式转换。

参考答案:

强制转换:

  • 转换为 numberparseInt()parseFloat()Number()
  • 转换为 stringString()toString()
  • 转换为 booleanBoolean()

隐式转换:

  • 隐式转换为 number:算术运算/比较运算,例如加、减、乘、除、相等(==)、大于、小于等;
  • 隐式转换为 string:与字符串拼接,例如 + "";
  • 隐式转换为 boolean:逻辑运算,例如或(||)、与(&&)、非(!);

291. 分析以下代码的执行结果并解释为什么。

var a = {n: 1};
var b = a;
a.x = a = {n: 2};

console.log(a.x)     
console.log(b.x)

参考答案:

运行结果:

undefined{n: 2}

分析:

首先,ab 同时引用了 {n: 1} 对象,接着执行到 a.x = a = {n: 2} 语句,虽然赋值是从右到左执行,但是点(.)的优先级比赋值符(=)要高,所以这里首先执行 a.x,相当于为 a(或者 b)所指向的 {n:1} 对象新增了一个属性 x,即此时对象将变为 {n: 1; x: undefined}。然后按正常情况,从右到左进行赋值,此时执行 a = {n: 2} 的时候,a的引用改变,指向了新对象 {n: 2},而 b 依然指向的是旧对象 {n: 1; x: undefined}。之后再执行 a.x = {n: 2} 的时候,并不会重新解析一遍 a,而是沿用最初解析 a.x 时候的 a,即旧对象 {n: 1; x: undefined},故此时旧对象的 x 的值变为{n: 2},旧对象为 {n: 1; x: {n: 2}},它依然被 b 引用着。

最后,a 指向的对象为 {n: 2}b 指向的对象为 {n: 1; x: {n: 2}}。因此输出 a.x 值为 undefined,输出 b.x 值为 {n: 2}

292. 分析以下代码的执行结果并解释为什么。

// example 1
var a = {}, b = '123', c = 123;  
a[b] = 'b';
a[c] = 'c';  
console.log(a[b]);

// example 2
var a = {}, b = Symbol('123'), c = Symbol('123');  
a[b] = 'b';
a[c] = 'c';  
console.log(a[b]);

// example 3
var a = {}, b = {key:'123'}, c = {key:'456'};  
a[b] = 'b';
a[c] = 'c';  
console.log(a[b]);

参考答案:

运行结果:

example 1c

example 2b

example 3c

分析:

这题考察的是对象的键名的转换。

  • 对象的键名只能是字符串和 Symbol 类型。
  • 其他类型的键名会被转换成字符串类型。
  • 对象转字符串默认会调用 String 方法。

因此 example 1c 作为键名后也是 '123',直接覆盖 a[b] 的值;而 example 2 中,Symbol 作为 ES6 中新增的基本数据类型,它的特点就是唯一,Symbol() 方法生成的值都是唯一的,里面的参数不会影响结果。因此在 example 2bc 是两个不同的键名;example 3 中,对象不能作为键名,因此 bc 都会通过 String() 方法转为字符串 [object Object]

293. 下面的代码打印什么内容?为什么?

var b = 10;
(function b() {
  b = 20;
  console.log(b)
})()

参考答案:

运行结果:

function b() { b = 20; console.log(b) } 分析:

JavaScript 解释器遇到非匿名立即执行函数(题目中的 b)时,会创建一个辅助的特定对象,然后将函数名称当作这个对象的属性,因此函数内部可以访问到 b,但是这个值又是只读的,所以对他的赋值并不生效,所以打印的结果还是这个函数,并且外部的值也没有发生更改。

294. 下面代码中,a 在什么情况下会执行输出语句打印 1

var a = ?;
if(a == 1 && a == 2 && a == 3){
     console.log(1);
}

参考答案:

分析:

这道题考查的知识点是:相等运算符(==)在作比较时会进行隐式转换,而如果操作数是引用类型,则会调用 toString()valueOf() 方法对引用类型数据进行隐式转换。

// 方法一:利用 toString()
let a = {
i: 1,
toString () {
 return a.i++;
}
}
if(a == 1 && a == 2 && a == 3) {
console.log('1');
}

// 方法二:利用 valueOf()
let a = {
i: 1,
valueOf () {
 return a.i++
}
}
if(a == 1 && a == 2 && a == 3) {
console.log('1');
}

// 方法三:利用数组(这个是真的骚)
var a = [1,2,3];
a.join = a.shift;
if(a == 1 && a == 2 && a == 3) {
console.log('1');
}

// 方法四:利用 Symbol
let a = {[Symbol.toPrimitive]: ((i) => () => ++i) (0)};
if(a == 1 && a == 2 && a == 3) {
console.log('1');
}

方法一和方法二没啥解释的了,解释下方法三和方法四。

方法三:

a.join = a.shift 的目的是将数组的 join 方法替换成 shift 方法。因为数组在参与相等比较时也会通过 toString() 将数组转为字符串,而该字符串实际上是数组中每个元素的 toString() 返回值经调用 join() 方法拼接(由逗号隔开)组成。现在我们将 join() 方法替换为了 shift() 方法,也就意味着数组在通过 toString() 隐式转换后,得到是 shift() 的返回值,每次返回数组中的第一个元素,而原数组删除第一个值,正好可以使判断成立。

方法四:

ES6 中提供了 11 个内置的 Symbo 值,指向语言内部使用的方法。Symbol.toPrimitive 就是其中一个,它指向一个方法,当该对象被转为原始类型的值时,会调用这个方法,并返回该对象对应的原始类型值。这里就是改变这个属性,把它的值改为一个闭包返回的函数。

295. 介绍前端模块化的发展。

参考答案:

  • IIFE:使用自执行函数来编写模块化(特点:在一个单独的函数作用域中执行代码,避免变量冲突)。

    (function(){
      return { data:[] }
    })()
    
  • AMD:使用 requireJS 来编写模块化(特点:依赖必须提前声明好)。

    define('./index.js',function(code){
        // code 就是index.js 返回的内容
    })
    
  • CMD:使用 seaJS 来编写模块化(特点:支持动态引入依赖文件)。

    define(function(require, exports, module) {  
      var indexCode = require('./index.js');
    });
    
  • CommonJSnodejs 中自带的模块化。

    var fs = require('fs');
    
  • UMD:通用模块规范,整合了 AMDCommonJS 模块化。

    (function (global, factory) {
      if (typeof exports === 'object' && typeof module !== undefined) { //检查CommonJS是否可用
        module.exports = factory(require('jquery'));
      } else if (typeof define === 'function' && define.amd) {      //检查AMD是否可用
        define('toggler', ['jquery', factory])
      } else {       //两种都不能用,把模块添加到JavaScript的全局命名空间中。
        global.toggler = factory(global, factory);
      }
    })(this, function ($) {
      function init() {
    
      }
      return {
        init: init
      }
    });
    
  • webpack(require.ensure)webpack 2.x 版本中的代码分割。

  • ES ModulesES6 引入的模块化,支持 import 来引入另一个 js

296. 请指出 document.onload 和 document.ready 两个事件的区别

参考答案:

页面加载完成有两种事件:一是 ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件);二是 onload,指示页面包含图片等文件在内的所有元素都加载完成。

297. 表单元素的readonlydisabled 两个属性有什么区别?

参考答案:

  • readonly
    • 不可编辑,但可以选择和复制;
    • 值可以传递到后台;
  • disabled:
    • 不能编辑,不能复制,不能选择;
    • 值不可以传递到后台;

298. 列举几种你知道的数组排序的方法。

参考答案:

// 方法一:选择排序
let ary = [5, 7, 8, 11, 3, 6, 4];
for (let i = 0; i < ary.length - 1; i++) {
for (let j = i + 1; j < ary.length; j++) {
 if (ary[i] < ary[j]) {
   [ary[i], ary[j]] = [ary[j], ary[i]];
 }
}
}
// 方法二:冒泡排序
let ary = [5, 7, 8, 11, 3, 6, 4];
for (let i = 1; i < ary.length; i++) { 
for (let j = 0; j < ary.length - i; j++) {  
 if (ary[j] < ary[j + 1]) {
   [ary[j], ary[j + 1]] = [ary[j + 1], ary[j]]
 }
}
}

299. 区分什么是“客户区坐标”、“页面坐标”、“屏幕坐标”?

参考答案:

  • 客户区坐标:鼠标指针在可视区中的水平坐标 (clientX) 和垂直坐标 (clientY);
  • 页面坐标:鼠标指针在页面布局中的水平坐标 (pageX) 和垂直坐标 (pageY);
  • 屏幕坐标:设备物理屏幕的水平坐标 (screenX) 和垂直坐标 (screenY);

300. 如何编写高性能的 JavaScript

参考答案:

  • 遵循严格模式:"use strict"
  • JavaScript 本放在页面底部,加快渲染页面
  • JavaScript 脚本将脚本成组打包,减少请求
  • 使用非阻塞方式下载 JavaScript 脚本
  • 尽量使用局部变量来保存全局变量
  • 尽量减少使用闭包
  • 使用 window 对象属性方法时,省略 window
  • 尽量减少对象成员嵌套
  • 缓存 DOM 节点的访问
  • 通过避免使用 eval()Function() 构造器
  • setTimeout()setInterval() 传递函数而不是字符串作为参数
  • 尽量使用直接量创建对象和数组
  • 最小化重绘 (repaint) 和回流 (reflow)

301. 下面的代码输出什么?

var a = function () { return 5 }
a.toString = function () { return 3 }
console.log(a + 7);

参考答案:

10

因为会自动调用 a 函数的 toString 方法。

本文链接:http://www.yanhongzhi.com/post/interview-javascript-6.html

-- EOF --

Comments