本文摘抄并总结一些JavaScript试题,答案在最下面。本文难免有不注意或有错的地方或有更好的方法,望指出更正学习。
虽然你变秃了,但是你变强了!!!
一、下面输出什么
1.let和var区别
var a
if (a) {
let a = 20
} else {
let a = 30
}
console.log(a) // undefined
// var是全局,let局部作用域,a在全局中未赋值,所以undefined
function fun(){
console.log(name) // undefined // var变量提升,相当于var name;console.log(name);name = 'lxf';赋值在后
console.log(age) // ReferenceError // let变量没有提升
var name = 'lxf'
let age = 18
}
var num = 10
var num = 20
console.log(num) // 20
var fn = NaN
function fn(){}
console.log(typeof fn) // number
var fn = function(){}
console.log(typeof fn) // function
2.setTimeout(类似setInterval。。。)
setTimeout 回调会在遍历结束后才执行,var是在全局作用域下的,等循环结束后直接输出最后值3,let在每一次循环内作用域中执行
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1) // 3 3 3
}
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1) // 0 1 2
}
3.箭头函数与普通函数
let b = 1
let obj = {
b: 10,
fn: function(){ // fn: function(){} <==> fn () {}
console.log(this.b)
},
fnn: () => {
console.log(this.b)
}
}
obj.fn() // 10
obj.fnn() // undefined this指window
4.对象调用
let c = 12
let obj = {
c: 45,
a: function(){
console.log(this.c)
}
}
let b = obj.a
b() // undefined,此时this是window(window调用obj里的a函数),this一般谁调用那属于谁
5.隐式符作用
console.log(+true) // 1 算数运算符(+)把true变成number类型,true变成1,false为0
console.log(+undefined) // NaN
console.log(!'lxf') // false 字符串'lxf'是一个真值,真值取反那么就假返回 false
let a = new Number(666) // 一个内建的函数构造器,是一个对象而不是number类型
let b = 666
console.log(a === b) // false
console.log(a == b) // true
function sum(a, b) {
return a + b
}
sum(1, '2') // 12 js中加号(+)是连字符
6.++a和a++区别(前者先加再赋值,后者先赋值再加)
let a = 10
b = 20 // 没有声明,就成了全局变量
console.log(b) // 20
let d = ++b+a++
console.log(d) // 31
let c = 0
consolelog(c++) // 0
consolelog(++c) // 2
consolelog(c) // 2
7.数组添加
let arr = [1, 2, 3]
arr[10] = 11
console.log(arr) // [ 1, 2, 3, <7 empty items>, 11 ]
8.对象取值
let a = {}
let b = {
key: 'jkl'
}
let c = {
key: 'iop'
}
a[b] = 123
a[c] = 456
console.log(a) // { '[object Object]': 456 }
console.log(a[c]) // 456
const obj1 = {
name: 'lxf',
love: true
}
const obj2 = {
name: 'wqq',
islove: 'love'
}
console.log(obj1[obj2["islove"]]) // true
console.log(obj1[obj2.islove]) // true
console.log(obj2['islove']) // love
console.log(obj1.obj2.islove) // Cannot read property 'islove' of undefined // obj1中没有obj2
9.hasOwnProperty和has和Set
const obj = {
1: 'a',
2: 'b',
3: 'c'
}
const set = new Set([1, 2, 3, 4, 5])
console.log(obj.hasOwnProperty('1')) // true
console.log(obj.hasOwnProperty(1)) // true
console.log(set.has('1')) // false
console.log(set.has(1)) // true
10.对象赋值
let a = {
name: 'lxf'
}
let b
b = a
a.name = 'wqq'
console.log(b.name) // wqq // 对象浅度复制,当设置两个对象彼此相等时,它们会通过引用进行交互,一边另一个也跟着变。避免这情况就是深度复制。
11.对象中有同名键
const obj = {
a: "one",
b: "two",
a: "three"
}
console.log(obj) // { a: "three", b: "two" } // 如果你有两个名称相同的键,则键会被替换掉。它仍然位于第一个键出现的位置,但是值是最后出现那个键的值。
12.continue跳过本次迭代
for (let i = 1; i < 5; i++) {
if (i === 3) continue
console.log(i) // 1, 2, 4 // 如果某个条件返回 true,则 continue 语句跳过本次迭代。
}
13.事件冒泡
<div onclick="console.log('div')">
<p onclick="console.log('p')">
Click here!
</p>
</div>
// p div
14.闭包
function foo(x) {
let a = 3
return function (y) {
console.log(x + y + (++a))
}
}
let bar = foo(2)
bar(10) // 16
15.基本类型
console.log(null + 1) // 1
console.log(undefined + 1) // NaN
console.log(NaN + 1 !== NaN + 1) // true NaN !== NaN
16.instanceof
console.log([] instanceof Object) // true
console.log([] instanceof Array) // true
console.log('somestr' instanceof String) //false
17.构造函数
function Study(){
Study.prototype.hello = function(){
console.log('hello')
}
}
let s = new Study()
console.log(Study.prototype) // Study { hello: [Function] }
console.log(s.hello) // [Function]
s.hello() // hello
18.基本类型
console.log([] === []) // false
console.log(null == 0) // false
console.log(null == undefined) // true
console.log(undefined == '0') // false
console.log(NaN == false) // false
console.log([] == false) // true
19.扩展运算符(es6)
let obj = {a: '1', b: '2', c: '3'}
let obj1 = {...obj}
console.log(obj === obj1) // false
obj1.a = 8
console.log(obj) // {a: '1', b: '2', c: '3'}
console.log(obj1) // {a: '8', b: '2', c: '3'}
20.解构赋值(es6)
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }
console.log(x) // 1
console.log(y) // 2
console.log(z) // {a: 3, b: 4}
21.对象合并(Object.assign)
let a = {a: '1'}
let b = {b: '2'}
let c = {c: '3'}
let obj = Object.assign(a, b, c) // 同名属性,则后面的属性会覆盖前面的属性
console.log(obj) // { a: '1', b: '2', c: '3' }
20.运算优先顺序
console.log('Value is ' + (NaN === NaN) ? 'Something' : 'Nothing') // Something
// 字符串连接比三目运算有更高的优先级
二、选择题
1.函数是对象
function fun() {
console.log('hello')
}
fun.name = 'lxf'
A: 正常运行!
B: SyntaxError. 你不能通过这种方式给函数增加属性。
C: undefined
D: ReferenceError
// A,函数是对象(除了基本类型之外其他都是对象),函数是一个拥有属性的特殊对象,并且属性也可被调用。
三、编程题
1.选择排序
首先从未排序序列中找到最大的元素,放到已排序序列的末尾,重复上述步骤,直到所有元素排序完毕。
时间复杂度均为o(n^2) 空间复杂度为o(1) 不稳定
function selectSort(arr){
let len = arr.length
let index
for (let i = 0; i < len - 1; i++) {
index = i
for (let j = i + 1; j < len; j++) {
if (arr[index] > arr[j]) index = j
if (index !== i) {
let res = arr[i]
arr[i] = arr[index]
arr[index] = res
}
}
}
return arr
}
2.冒泡排序
比较相邻的两个元素,如果前一个比后一个大,则交换位置。再进入下一轮循环比较。
function bubbleSort(arr){
let len = arr.length
for (let i = 0; i < len; i++) {
for (let j = i + 1; j < len; j++) {
if (arr[i] > arr[j]) {
let temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
}
}
return arr
}
3.插入排序
每次将一个数插入到有序的数组中去
function insertSort(arr){
let j, len = arr.length, temp
for(let i = 1; i < len; i++){
j = i
temp = arr[j]
while (--j > -1) {
if (arr[j] > temp) {
arr[j+1] = arr[j]
} else {
break
}
}
arr[j+1] = temp
}
return arr
}
4.快速排序
将待排序数组逐步划分两个部分,其中左半部分都要小于右半部分,再将左右部分分别进行快速排序,整个过程可采用递归进行,直到排成一个有序数列。
function quickSort(arr){
if (arr.length <= 1) return arr
let pivotIndex = Math.floor(arr.length / 2) // 取基准点
let pivot = arr.splice(pivotIndex, 1)[0] // 取基准点的值,splice(index,1)函数可以返回数组中被删除的那个数
let left = [] // 存放比基准点小的数组
let right = [] // 存放比基准点大的数组
for (let i = 0; i < arr.length; i++) { // 遍历数组,进行判断分配
if (arr[i] < pivot) {
left.push(arr[i]) // 比基准点小的放在左边数组
} else {
right.push(arr[i]) // 比基准点大的放在右边数组
}
}
//递归执行以上操作,对左右两个数组进行操作,直到数组长度为<=1
return quickSort(left).concat([pivot], quickSort(right))
}
5.随机打乱数组
let arr = [1, 3, 2, 4, 2, 3, 1]
function randomArr(arr){
return arr.sort(() => 0.5 - Math.random())
}
6.牙刷5元,香皂2元、洗发水15元 100元正好花完有多少种可能?
let num = 0
for (let i=0; i<=20; i++) {
for (let j=0; j<=50; j++) {
for (let x=0; x<=6; x++) {
if (5*i+2*j+15*x === 100) {
num++
}
}
}
}
console.log(num) // 44
7.根据json数组中两个key相同进行去重
法一:
let arr = [
{x: 11, y: 9, z: 1},
{x: 12, y: 9, z: 2},
{x: 13, y: 9, z: 2},
{x: 13, y: 10, z: 2},
{x: 13, y: 11, z: 1},
{x: 13, y: 10, z: 1}
]
const uniqueTwoKey = (arr, a, b) => {
const dict = {}
for (const item of arr) {
dict[item[a] + ',' + item[b]] = item
}
return Object.values(dict)
}
console.log(uniqueTwoKey(arr, 'x', 'y'))
法二:
const uniqueTwoKey = (arr, a, b) => {
const dict = {}
return arr.filter(e => {
const key = [e[a], e[b]].join("|")
if (dict[key]) return false
dict[key] = true
return true
})
}
console.log(uniqueTwoKey(arr, 'x', 'y'))
结果:
[
{ x: 11, y: 9, z: 1 },
{ x: 12, y: 9, z: 2 },
{ x: 13, y: 9, z: 2 },
{ x: 13, y: 10, z: 1 },
{ x: 13, y: 11, z: 1 }
]