思考性问题

第一题:['1', '2', '3'].map(parseInt) what & why ?
答案:[1, NaN, NaN]
// map参数使用
arr.map(function(currentValue, index, arr) {})
// 第一参数为当前被处理的元素,第二参数为该元素索引

// 而parseInt也是一个函数,解析字符串为指定基数
parseInt(string, radix);
// 第一参数为被处理的字符串,第二参数为解析的基数
当 radix 为 0 时,按照基数为10处理, 返回 1;
当 radix 为 1 时,parseInt 基数范围是 2 ~ 36,无法解析, 返回 NaN;
当 radix 为 2 时,二进制只能存在0 和 1,最后返回 NaN。
第二题:将数组扁平化并去除其中重复数据,最终得到一个升序且不重复的数组
var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
Array.from(new Set(arr.flat(Infinity))).sort((a, b) => {return a - b});
第三题:请把两个数组 [‘A1’, ‘A2’, ‘B1’, ‘B2’, ‘C1’, ‘C2’, ‘D1’, ‘D2’] 和 [‘A’, ‘B’, ‘C’, ‘D’],合并为 [‘A1’, ‘A2’, ‘A’, ‘B1’, ‘B2’, ‘B’, ‘C1’, ‘C2’, ‘C’, ‘D1’, ‘D2’, ‘D’]。
let arr1 = ['A1', 'A2', 'B1', 'B2', 'C1', 'C2', 'D1', 'D2'];
let arr2 = ['A', 'B', 'C', 'D'].map(item => item + 3);
let arr3 = [...arr1, ...arr2].sort().map(item => {
    if (item.includes('3')) {
         return item.split('')[0];
    }
    return item;
})
第四题:改造下面的代码,使之输出0 - 9。
for (var i = 0; i< 10; i++){
    setTimeout(() => {
        console.log(i);
    }, 1000)
}
// 解法一:ES6 let
for (let i = 0; i < 10; i ++) {
    setTimeout(() => {
        console.log(i);
    }, 1000)
}
// 解法二: 自执行函数
for (let i = 0; i < 10; i ++) {
    (function(i) {
        setTimeout(() => {
            console.log(i);
        }, 1000)
    })(i);
}
// 解法三:setTimeout 第三参数,作为 callback 的参数
for (var i = 0; i < 10; i ++) {
    setTimeout((i) => {
        console.log(i);
    }, 1000, i)
}
第五题:以下代码打印的是什么?为什么?
var a = 10;
(function a() {
    a = 20;
    console.log(a);
    console.log(window.a);
})();
console.log(a);

打印结果为: 函数a  10  10
因为是自执行函数,产生了自己的作用域,所有不会修改全局 window 下的变量 a。
而自执行函数中对自身进行赋值是无效的代码, 所以 a = 20 并未生效,但在自执行函数中可以定义与之同名的作用域变量 (看第六题)。
第六题:简单改造以下代码,使之打印10 或 20
var b = 10;
(function b(){
    b = 20;
    console.log(b); 
})();

// 打印 10
var b = 10;
(function b() {
    b = 20;
    console.log(window.b);
})();
// 打印20
var b = 10;
(function b() {
    var b = 20;
    console.log(b);
})();
第七题:实现一个 sleep 函数,比如 sleep(1000) 意味着等待1000毫秒,可从 Promise、Generator、Async/Await 等角度实现。
// Promise实现:
const sleep = (time) => {
    return new Promise(resolve => setTimeout(resolve, time))
}
sleep(1000).then(() => {
    console.log("1秒后调用then方法");
})

// async实现:
const sleep = (time) => {
    return new Promise(resolve => setTimeout(resolve, time))
}
async function asyncFun() {
    console.log("发生在sleep函数之前");
    await sleep(1000).then(() => console.log("执行sleep函数"));
    console.log("发生在sleep函数之后");
}
asyncFun();

// Generator实现:
function* sleepGenerator(time) {
    yield new Promise((resolve) => {
        setTimeout(resolve, time);
    })
}
sleepGenerator(1000).next().value.then(() => console.log("1秒后执行then方法"));
第八题:以下代码执行结果并解释为什么
var obj = {
    '2': 3,
    '3': 4,
    'length': 2,
    'splice': Array.prototype.splice,
    'push': Array.prototype.push
}
obj.push(1)
obj.push(2)
console.log(obj)

打印结果:[ , , 1, 2, splice: ƒ, push: ƒ]。
首先这个对象的key是字符串的数字,并且存在length属性,是一个类数组,所以key表示类数组的下标。当调用数组的push方法时,会向类数组末尾添加元素,由于length定义为2,所以会在第二个元素后面添加,对应的下标为2,所以 push(1) 替换了 下标为 2 的值(3),最后 length 会取决于最初定义的length和对类数组的操作,length最初为2,添加了两个元素后length变为 4。

第九题:实现 (5).add(3).minus(2) 功能。
Number.prototype.add = function(num) {
    return this + num;
}
Number.prototype.minus = function(num) {
    return this - num;
}
let number = (5).add(3).minus(2);
第十题:输出以下代码的执行结果并解释为什么
var a = {n: 1};
var b = a;
a.x = a = {n: 2};

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

执行结果是: a.x = undefined,b.x = {n: 2}
关键点在于:
1、优先级: . (点) 的优先级高于 = ,所以先执行和 a.x,堆内存中的 {n: 1} 就会变成 {n: 1, x: undefined},相应的 b 也发生改变,因为指向同一对象。
2、赋值操作是从右到左:所以先执行a = {n: 2},此时a的引用就被改变了,然后返回值又赋值给了a.x, 需要注意这里的 a.x 是第一步中的 {n: 1, x: undefined} 那个对象, 其实就是对象 b,相当于访问了 b.x = {n: 2}。

第十一题:某公司 1 到 12 月份的销售额存在一个对象里面,如下:{1:222, 2:123, 5:888},请把数据处理为如下结构:[222, 123, null, null, 888, null, null, null, null, null, null, null]。
let info = {1: 222, 2: 123, 5: 888};
// 方式一:
let arr = new Array(12).fill(null); // 创建一个长度为10并且每个元素都为null的数组
Object.keys(info).forEach(key => {
    arr[key - 1] = info[key];
})
console.log(arr);
// 方式二:
const result = Array.from({length: 12}).map((_, index) => info[index + 1] || null); // 将length为12的类数组转为数组,通过map映射。
console.log(result);
十二题:给定两个数组,写一个方法来计算它们的交集。
function union(arr1, arr2) {
    return arr1.filter(item =>{
        return arr2.indexOf(item) > - 1;
    })
}
const arr1 = [1,2,2,1];
const arr2 = [2,3,2];
console.log(union(arr1, arr2)); // [2, 2]
十三题:随机生成一个长度为 10 的整数类型的数组,例如 [2, 10, 3, 4, 5, 11, 10, 11, 20],将其排列成一个新数组,要求新数组形式如下,例如 [[2, 3, 4, 5], [10, 11], [20]]。
let arr = [];
for (var i = 0; i < 10; i ++) {
    arr.push(Math.floor(Math.random() * 100));
}
function formArray(arr) {
    const sortedArr = Array.from(new Set(arr)).sort((a, b) => a - b); // 先进行去重、排序
    const map = new Map();  // 利用map进行存储

    sortedArr.forEach((item) => {
        const key = Math.floor(item / 10);
        const group = map.get(key) || [];
        group.push(item);

        map.set(key, group);
    });

    return [...map.values()];
}
let value = formArray(arr);

十四题:如何把一个字符串的大小写取反(大写变小写小写变大写),例如 ’AbC’ 变成 ‘aBc’ 。

function processString (str) {
    var arr = str.split('');
    var new_arr = arr.map((item) => {
        return item === item.toUpperCase() ? item.toLowerCase() : item.toUpperCase();
    });
    return new_arr.join('');
}
十五题:实现一个字符串匹配算法,从长度为 n 的字符串 S 中,查找是否存在字符串 T,T 的长度是 m,若存在返回所在位置。
const find = (S, T) => {
  if (S.length < T.length) return -1
  for (let i = 0; i < S.length; i++) {
    if (S.slice(i, i + T.length) === T) return i
  }
  return -1
}
十六题:输出以下代码运行结果:
// 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]);

这道题主要考察对象的键名的转换:

  • 对象的键名只能是字符串和 Symbol 类型。
  • 其他类型的键名会被转为字符串。
  • 在将对象转字符串时默认调用 toString 方法
// example 1
var a={}, b='123', c=123;  
a[b]='b';
a[c]='c';    // c 的键名会被转为字符串 '123',这里会把b覆盖掉
console.log(a[b]); // 输出 c

// example 2
var a={}, b=Symbol('123'), c=Symbol('123');  
a[b]='b';    // b 是 Symbol 类型, 不需要转换
a[c]='c';    // c 是 Symbol  类型, 不需要转换,Symbol 表示唯一性,任何一个 Symbol值都是不等的,所以不会覆盖 b
console.log(a[b]);   // 输出 b

// example 3
var a={}, b={key:'123'}, c={key:'456'};  
a[b]='b';    // 对象类型转字符串时会调用toString方法转换成字符串 [object Object]
a[c]='c';    // 对象类型转字符串时会调用toString方法转换成字符串 [object Object]
console.log(a[b]);     // 输出 c
十七题:打印出 1 - 10000 之间的所有对称数 例如:121、1331 等
[...Array(10000).keys()].filter((x) => { 
    return x.toString().length > 1 && x === Number(x.toString().split('').reverse().join('')) 
})
十八题:算法题「移动零」,给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序
function zeroMove(array) {
    let len = array.length;
    let j = 0;    // 控制末尾第一个0的起始位置,防止死循环
    for(let i=0;i<len-j;i++){
        if(array[i]===0){
            array.push(0);
            array.splice(i,1);
            i --;   
            j ++;
        }
    }
    return array;
}
十九题:请实现一个 add 函数,满足以下功能。
add(1);           // 1
add(1)(2);      // 3
add(1)(2)(3);// 6
add(1)(2, 3); // 6
add(1, 2)(3); // 6
add(1, 2, 3); // 6
function add(){
    var _args  = [].slice.apply(arguments);
    var _adder = function (){
        _args.push(...arguments);
        return _adder;  // 每次都返回这个函数,并利用闭包拿到 _args
    }
    _adder.valueOf = function(){
        return _args.reduce(function(a,b)
            return a+b;
        })
    }
    return _adder;
}
console.log(+add(1)(2)(3));
二十题:给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
function anwser (arr, target) {
    let map = {}
    for (let i = 0; i < arr.length; i++) {
        map[arr[i]] = i
    }
    for (let i = 0; i < arr.length; i++) {
        var d = target - arr[i]
        if (map[d]) {
            return [i, map[d]]
        }
    }
    return new Error('404 not found')
}
二十一:在输入框中如何判断输入的是一个正确的网址。
const isUrl = urlStr => {
    try {
        const { href, origin, host, hostname, pathname } = new URL(urlStr)
        return href && origin && host && hostname && pathname && true
    } catch (e) {
        return false
    }
}
二十二:(京东)请写出如下代码的打印结果:
function Foo() {
    Foo.a = function() {
        console.log(1)
    }
    this.a = function() {
        console.log(2)
    }
}
Foo.prototype.a = function() {
    console.log(3)
}
Foo.a = function() {
    console.log(4)
}
Foo.a();
let obj = new Foo();
obj.a();
Foo.a();

执行结果: 4 2 1
解题:

function Foo() {            // 1、首先这里定义了Foo方法,但没有调用,所以没有执行内部代码
    Foo.a = function() {
        console.log(1)
    }
    this.a = function() {
        console.log(2)
    }
}
Foo.prototype.a = function() {
    console.log(3)
}
Foo.a = function() {
    console.log(4)
}
Foo.a(); // 这里使用了Foo,但也没有通过 () 调用,并且使用Foo.a不会在原型上查找。 这里打印 4
let obj = new Foo(); // 通过new 调用 Foo 返回一个对象,只有对象才可以访问 this 和 原型prototype,并且对象访问a方法时,不会去查找 Foo.a 定义的a方法
obj.a();  // 原型上有a方法,但函数体内也有a方法,这里打印 2
Foo.a(); // 由于之前 通过new 调用了一次, 执行了函数体内的 Foo.a,这里打印 1
第二十三题: 求c的结果
var a = function() {
    this.b = 1;
}
var b = function() {
    var b = new a().b;
    return 5 + b;
}
var c = b();

答案是 6。在 b 函数内部定义了变量 b,当 new a().b 时,会先执行new a(),并返回结果对象 {b: 1},再访问 .b 得到 1。

第二十四题:
a = 1;
b = 2;
c = 2;
while(a < b < c) {
    t = a;
    a = b;
    b = t;
    c --;
}
console.log('' + a + b + c);

答案: 120。
解题:第一次进入 while 时,a < b 成立并返回 true,当 < c 时,< 会进行隐式转换,将 true 转为 1 后小于 c 成立;第二次进入 while 时, a < b 不成立返回 false,此时 c 为 1, 与 c 比较时,遇 < 进行隐式转换,将 false 转为 0,0 < 1 所以成立,这时 c --, 也为0,结束 while 循环。

第二十五题:
var length = 10;
function fn() {
    console.log(this.lenght);
}

var obj = {
    length: 5,
    methods: function(fn) {
        fn();
        arguments[0]();
    }
}
obj.methods(fn);

答案: 10, 1
解题:第一次执行: fn(),表示全局调用,this指向window,所以打印 10,当第二次执行: arguments0 时,this并非指向 obj,而是 arguments,所以打印的是 arguments 的长度 1。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351

推荐阅读更多精彩内容