【javaScript】- 笔试题合集(长期更新,建议收藏,目前已更新至43题)

本篇文章用于记录javaScript相关的一些题目,且长期更新,建议收藏!

1.使用原生js,通过addEventListener给每一个li元素绑定一个click事件,输出他们的顺序

window.onload = function test() {
    var liList = document.getElementsByTagName("li");
    console.log(liList)
    for (var i = 0; i < liList.length; i++) {
        // 这里使用立即执行函数后,此时fun函数的[[scope]][0]=当前这个立即执行函数
        // 而每次for都会形成一个新的匿名函数,所以每个fun函数的[[scope]][0]是独一无二的,保存的i都为当前的i
        (function (j) {
            liList[j].addEventListener("click", function fun() {
                console.log(j)
            })
        }(i))
    }
}

2.写出以下打印信息

a = 100;
function demo(e) {
    function e() { }
    arguments[0] = 2;
    console.log(e);//2
    if (a) {
        var b = 123;
        function c() {
            //猪都能做出来
        }
    }
    var c;
    a = 10;
    var a;
    console.log(b);//undefined
    f = 123;
    console.log(c);//以前打印的是function c(){};现在打印undefined
    console.log(a);//10
}
var a;
demo(1);
console.log(a);//100
console.log(f);//123

3.写一个方法,求一个字符串的字节长度(提示:字符串有一个方法charCodeAt(),一个中文占两个字节,一个英文占一个字节,当返回值是<=255 时,为英文,当返回值>255时为中文)

function test(target) {
    var count = target.length;
    for (var i = 0; i < target.length; i++) {
        if (target[i].charCodeAt() > 255) {
            count++
        }

    }
    return count
}

4.写出以下打印信息

// 4.
var f = (
    function f() {
        return "1"
    },
    function g() {
        return 2
    }
)()
// 首先明确一点,关于逗号计算符的使用:先看逗号前的表达式,如果要计算会进行计算;再看逗号后的表达式,如果要计算会进行计算,最后返回逗号后表达式的计算结果
// var f = (...)(),会先执行前一个括号的内容,其相当于一个表达式。()中有逗号运算符,执行逗号运算符的机制,会返回逗号后的内容,也就是g函数。
// 然后执行后面的括号,也就是执行符号,将g函数进行执行,会返回数字2,并赋值给f
console.log(typeof f)
// typeof f 相当于 typeof(2) 为"number"

5.写出以下打印信息

var x = 1;
if (function f() { }) {
    x += typeof f
}
// if (function f() { }) = true,因为if括号中的内容当成一个表达式执行并将其转化为boolean值,f是个函数,所以为true,并且此时函数作为一个表达式执行了,被销毁了
// x += typeof f =》 x = x + typeof f = 1 + 'undefined' = '1undefined'。因为f此时是一个未被定义的变量,这种情况typeof f会返回"undefined"
console.log(x); //打印'1undefined'

6.使用递归实现n的阶乘

//①抽象规律:n! = n * (n - 1)!  ②出口:n为1时,为1
function factorial(n) {
    if (n == 1) {
        return 1;
    }
    return n * factorial(n - 1)
}

7.使用递归实现斐波那契数列

//①抽象规律:n = (n-1) + (n-2)  ②出口:n为1和2时,为1
function sequence(n) {
    if (n == 1 || n == 2) {
        return 1;
    }
    return sequence(n - 1) + sequence(n - 2)
}

8.写出以下打印信息

var str = false + 1; //+号,若两侧没有字符串,会致力于将其转化为数字进行计算,通过隐式调用Number实现。Number(false)+Number(1)=0+1=1
console.log(str); //打印1
var demo = false == 1; //赋值符号优先级最后,先看false == 1,==会致力于将两者转换为相同,通过隐式调用Number实现。Number(false)==Number(1),即0==1,得出值为false,并将值赋值给demo
console.log(demo); //打印false
//typeof (a):结果为"undefined"。因为是字符串的undefined,所以会继续往后看
//-true:结果为1。因为-会将其致力于转换为数字类型,通过隐式调用Number实现。Number(true)=1
//+undefined:结果为NaN。因为+会将其致力于转换为数字类型,通过隐式调用Number实现。Number(undefined)=NaN
//-true + (+undefined) + "":结果为"NaN",会进入判断。因为 1+NaN,+会致力于将其转化为数字进行计算,通过隐式调用Number实现,值为NaN,NaN+""。+一边有字符串,会致力于将其转化为字符串,进行拼接,所以='NaN'
if (typeof (a) && -true + (+undefined) + "") {
    console.log("1")//打印"1"
}
// *优先级高,先算"11" * 2,*会会致力于将其转化为数字进行计算,通过隐式调用Number实现。得值为22,所以11 + "11" * 2 = 11+22=33,会等于33,进入判断
if (11 + "11" * 2 == 33) {
    console.log("2")//打印"2"
}
//!!" "为true;!!"" 为false;!!false为false。则!!" " + !!"" - !!false 为1+0+0=1,为真,不继续往后看了
!!" " + !!"" - !!false || console.log("3")

9.写出以下打印信息

// 1.全局预编译,得到GO:{glob:undefined,demo:undefined,a:function a(){...}},得到a.[[scope]][0]为GO:{...}
function a() {
    function b() {
        var bbb = 234;
        // 沿着作用域链从上往下找,先找第0位即bAO,没有则继续往下,找第1位aAO,返回123
        console.log(aaa);//123
    }
    // 4.将aaa修改为123。此时aAO:{aaa:123,b:function b(){...}}
    var aaa = 123;
    // 5.将b函数返回出去,并赋值给demo
    return b;
    // 6.a函数执行完毕,销毁a的执行期上下文,此时a.[[scope]][0]为GO:{...}
}
// 2.改变glob的值,此时GO:{glob:100,demo:undefined,a:function a(){...}}
var glob = 100;
// 3.执行a(),进行a函数的预编译,得到a.[[scope]][0]为aAO:{aaa:undefined,b:function b(){...}};a.[[scope]][1]为GO:{...}
// 得到b.[[scope]][0]为aAO:{...};a.[[scope]][1]为GO:{...}
var demo = a();
// 7.执行demo(),也就是执行b函数,进行b函数的预编译,得到b.[[scope]][0]为bAO:{bbb:undefined};b.[[scope]][1]为aAO:{...};b.[[scope]][2]为GO:{...}
demo();

10.写出以下打印信息

// 1.全局预编译,得到GO:{demo:undefined,a:function a(){...}},得到a.[[scope]][0]为GO:{...}
function a() {
    // 3.将mum值赋值位100.此时aAO:{num:100,b:function b(){...}}
    var num = 100;
    function b() {
        // 7.将num值+1,沿着作用域链从上往下找,先找第0位即bAO,没有则继续往下,找第1位aAO,将mum的值重写为101
        // 11.将num值+1,沿着作用域链从上往下找,先找第0位即bAO,没有则继续往下,找第1位aAO,将mum的值重写为102
        num++;
        // 8.沿着作用域链从上往下找,先找第0位即bAO,没有则继续往下,找第1位aAO,返回101
        // 12.沿着作用域链从上往下找,先找第0位即bAO,没有则继续往下,找第1位aAO,返回102
        console.log(num);
        // 9.b函数执行完毕,销毁b的执行期上下文,此时b.[[scope]][0]为aAO:{...};a.[[scope]][1]为GO:{...}
        // 13.b函数执行完毕,销毁b的执行期上下文,此时b.[[scope]][0]为aAO:{...};a.[[scope]][1]为GO:{...}
    }
    // 4.将b函数返回出去,并赋值给demo
    return b;
    // 5.a函数执行完毕,销毁a的执行期上下文,此时a.[[scope]][0]为GO:{...}
}
// 2.执行a(),进行a函数的预编译,得到a.[[scope]][0]为aAO:{num:undefined,b:function b(){...}};a.[[scope]][1]为GO:{...}
// 得到b.[[scope]][0]为aAO:{...};a.[[scope]][1]为GO:{...}
var demo = a();
// 6.执行demo(),也就是执行b函数,进行b函数的预编译,得到b.[[scope]][0]为bAO:{};b.[[scope]][1]为aAO:{...};b.[[scope]][2]为GO:{...}
demo();
// 10.执行demo(),也就是执行b函数,进行b函数的预编译,得到b.[[scope]][0]为bAO:{};b.[[scope]][1]为aAO:{...};b.[[scope]][2]为GO:{...}
demo();

11.写出以下打印信息

var x = 1, y = z = 0;
function add(n) {
    return n = n + 1;
}
y = add(x);
function add(n) {
    return n = n + 3;
}
z = add(x)
// 答案是x=1,y=x=4
// 因为有预编译环节,会将add函数提前放置到执行期上下文中,且只能有一个add属性名,且后面出现的会覆盖前面的函数声明
// 所以y和z调用的add都是后面一个add函数。都为4

12.下面代码中console.log()的结果是[1,2,3,4,5]的选项是?

// A
function foo(x) {
    console.log(arguments);
}
foo(1, 2, 3, 4, 5);
// B 这种写法不报错也不输出,相当于把(1, 2, 3, 4, 5)这个当作一个表达式执行了,并不是当成方法调用
function foo(x) {
    console.log(arguments);
    return x
} (1, 2, 3, 4, 5);
// C
(function foo(x) {
    console.log(arguments);
    return x
})(1, 2, 3, 4, 5);
// D
function foo() {
    bar.apply(null, arguments)
}
function bar(x) {
    console.log(arguments)
}
foo(1, 2, 3, 4, 5);
// 答案是A、C、D

13.写出以下打印信息

function employee(name, code) {
    // 这里使用this赋值是直接赋值的固定值,而不是传入的实参
    this.name = 'wangli';
    this.code = 'A001';
}
var newemp = new employee("zhangming", 'A002');
console.log("雇员姓名:" + newemp.name); // 雇员姓名:wangli
console.log("雇员代码:" + newemp.code); //雇员代码:A001

14.写出以下打印信息

var str = 'abc';
str += 1;//str = str + 1 = 'abc' + 1 = 'abc1'
var test = typeof (str);// test = typeof('abc1') = 'string'
if (test.length == 6) { //test.length = 6 进入判断
    // String(test).sign = '...' 而后销毁该包装类
    test.sign = 'typeof的返回值可能为String';
}
// String(test).sign = undefined
console.log(test.sign) //undefined

15.写出以下打印信息

function Person(name, age, sex) {
    var a = 0;
    this.name = name;
    this.age = age;
    this.sex = sex;
    function sss() {
        a++;
        console.log(a);
    }
    this.say = sss;
}
var oPerson = new Person();
// say是Person构造函数中的函数,形成了闭包,所以oPerson对象在调用say方法时,所使用的a是同一个
oPerson.say();//1
oPerson.say();//2
// 这里oPerson1和前面的oPerson不是同一个对象,是全新创建了一个对象,两者之间无任何联系
var oPerson1 = new Person();
oPerson1.say();//1

16.请问以下表达式的结果是什么?

parseInt(3,8); // 3。以8为基地把3转为10进制的数,依旧为3
parseInt(3,2); // NaN。因为2进制没有3这个数,所以有误,返回结果为NaN
parseInt(3,0); // 3 或者 NaN。因为没有0进制。有些浏览器认为有误,返回NaN,有些则认为0进制那就是没有,直接忽略返回3

17.看看下面alert的结果是什么?

function b(x, y, a) {
    arguments[2] = 10;
    alert(a);//10
}
b(1, 2, 3);
// 如果函数体改成下面,结果又会是什么?
a = 10;
alert(arguments[2]);//10
// 答案都是10,因为实参列表和形参是互相映射的,一个改了另一个也会跟着改。

18.写出以下打印信息

var name = '222';
var a = {
    name: '111',
    say: function () {
        console.log(this.name)
    }
}
var fun = a.say;//相当于把a.say放到了fun上
fun();//fun在全局执行,this指向window,打印"222"
a.say();//this指向a,打印"111"
var b = {
    name: "333",
    say: function (fun) {
        fun();
    }
}
b.say(a.say);//b的say方法里的this指向的是b,此时里面的fun()是谁也没调用的情况,所以走的预编译环节,指向的是window,打印111
b.say = a.say;//将a的say方法放到b.say上
b.say();//执行b.say,b调用的,指向b,所以打印333

19.写出以下打印信息

var foo = '123';
function print() {
    var foo = '456';
    this.foo = '789';
    console.log(foo);//456.会先在AO中找,找到foo为456,返回
}
print();

20.写出以下打印信息

var foo = '123';
function print() {
    this.foo = '234';//print是在全局调用的,此时this会指向全局,所以会将全局的foo变成234
    console.log(foo);//234,会先在AO中找,AO中没有,则沿着作用域链找,找到全局foo为234,返回
}
print();

21.写出以下打印信息

var foo = '123';
function print() {
    this.foo = '234';//此时print是通过new关键字调用的,所以此时this会指向隐式自己创建的this
    console.log(foo);//123,会先在AO中找,AO中没有,则沿着作用域链找,找到全局foo为123,返回
}
new print();

22.①运行test()和②new test()的结果分别是什么?

var a = 5;
function test() {
    a = 0;
    alert(a);//①0  ②0
    alert(this.a);//5 ②undefined
    var a;
    alert(a)//①0 ②0
}

23.写出以下打印信息

function print() {
    console.log(foo);//undefined
    var foo = 2;
    console.log(foo);//2
    console.log(hello);//报错
}
print();

24.写出以下打印信息

function print() {
    var test;
    test();
    function test() {
        console.log(1);//1
    }
}
print();

25.写出以下打印信息

function print(){
    var x = 1;
    if(x == '1')console.log("One!");//One!会尽量让两边相等,此时调用Number()将其都转为数字,所以相等,会打印
    if(x === '1')console.log("Two!");//不不打印.===要完全相等才行
}
print();

26.写出以下打印信息

function print() {
    var marty = {
        name: "marty",
        printName: function () { console.log(this.name); }
    }
    var test1 = { name: "test1" };
    var test2 = { name: "test2" };
    var test3 = { name: "test3" };
    test3.printName = marty.printName;
    var printName2 = marty.printName.bind({ name: 123 });
    marty.printName.call(test1);//test1
    marty.printName.apply(test2);//test2
    marty.printName();//marty
    printName2();//123
    test3.printName();//test3
}
print()

27.写出以下打印信息

var bar = { a: "002" };
function print() {
    // 将全局的bar.a修改为了a
    bar.a = 'a';
    Object.prototype.b = 'b';
    return function inner() {
        console.log(bar.a);//先找自身没有bar变量,沿着作用域链找上级print的AO也没有,再继续找到全局,发现有,返回a
        console.log(bar.b);//先找自身没有bar变量,沿着作用域链找上级print的AO也没有,再继续找到全局,发现有,但是没有b这个属性,则会沿着原型链往上找.找到原型链上有b返回b
    }
}
print()()
console.log(window.bar)

28.写出以下打印信息

Person.prototype.name = 'hu';
function Person() {
    // new时会隐式调用:var this = {__proto__:Person.prototype}
}
Person.prototype = {
    name: "luo"
};
var person = new Person();
console.log(person.__proto__.name);// 打印luo
// 代码运行过程
// 1.预编译 GO:{person:undefined,Person:function Person(){}}
// 2.执行Person.prototype.name = 'hu'
// 3.执行Person.prototype = {name: "luo"};
// 4.执行person = new Person()。也就是说这时候才会发生将原型赋值给this中的__proto__属性
// 5.执行console.log(person.__proto__.name)。Person.prototype是后修改的那个,为luo

29.写出以下打印信息

Person.prototype = {
    name: "a",
    sayName: function () {
        console.log(this.name);//a
        console.log(this);//a
    }
};
function Person() {
    // new时会隐式调用:var this = {__proto__:Person.prototype}
}
var person = new Person();
person.sayName()
Person.prototype.sayName();
// 代码运行过程
// 1.预编译 GO:{person:undefined,Person:function Person(){}}
// 2.执行Person.prototype = {...}
// 3.执行person = new Person()。会发生将原型赋值给this中的__proto__属性
// 4.执行person.sayName()。也就是会运行person原型链上的sayName方法,
// 5.执行console.log(this.name)。因为是person对象调用的方法,所以里面的this会指向该对象
//   而person本身并没有name属性,于是会沿着原型链找,找到其原型上有name为a,返回
// 6.执行Person.prototype.sayName()。因为是Person.prototype对象调用的方法,所以里面的this会指向该对象,返回name的值为a

30.写出以下打印信息

Person.prototype = {
    height: 100
}
function Person() {
    // new时会隐式调用:var this = {__proto__:Person.prototype}
    this.eat = function () {
        this.height++;
    }
}
var person = new Person();
person.eat();
console.log(person);//{height:101,eat:function eat(){...}}
console.log(person.__proto__);//{height:100}
// 代码运行过程
// 1.预编译 GO:{person:undefined,Person:function Person(){}}
// 2.执行Person.prototype = {...}
// 3.执行person = new Person()。会发生将原型赋值给this中的__proto__属性
// 4.执行person.sayName()。也就是会运行person原型链上的sayName方法,
// 5.执行person.eat()。因为是person对象调用的方法,所以里面的this会指向该对象,
//   而person本身并没有height属性,于是会沿着原型链找,找到其原型上有height为100,取得该值并+1为101,
//   然后为自身创建一个height对象,值为101。也就是说原型上的height值不变,自身多了height属性为101
// 6.执行console.log(person)。打印person对象,为{height:101,eat:function eat(){...}}
// 7.执行console.log(person.__proto__)。打印person.__proto__对象,为{height:100}

31.以下哪些表达式的结果为true?

// A
undefined == null;
// B
undefined === null;
// C
isNaN('100');//Number('100') = 100,是数字类型,不是NaN,所以为false
// D
parseInt('1a') == 1
// E
({}) == ({});//引用值比较的是地址,这是两个不同的对象,所以地址并不相等为false
// 答案是A、D

32.实现浅拷贝

function clone(origin, target) {
    var target = target || {};
    for (var key in origin) {
        target[key] = origin[key]
    }
    return target
}

33.实现深拷贝

function deepClone(origin, target) {
    var target = target || {};
    for (var key in origin) {
        // 先判断是否为原始值,原始值直接拷贝,不是原始值则继续判断
        if (typeof (origin[key]) == "object") {
            //不为原始值,判断为对象还是数组
            var obj = Object.prototype.toString.call(origin[key] === "[object Array]") ? [] : {};
            target[key] = deepClone(origin[key], obj)
        } else {
            //为原始值
            target[key] = origin[key]
        }
    }
    return target
}

34.将下列有序数组arr变成一个乱序数组

var arr = [1,2,3,4,5,6]
arr.sort(function(a,b){
    return Math.random() - 0.5; //Math.random()会生成[0,1)的随机数
})

35.通过对象中的age属性给下列arr数组进行升序排序

var hu = {
    name:'hu',
    age:12
}
var luo = {
    name:'luo',
    age:18
}
var mo = {
    name:'mo',
    age:6
}

var arr = [hu,luo,mo]
for(var i = 0; i < arr.length; i++){
    arr.sort(function(a,b){
        return a.age - b.age
    })
}

36.将下列arr数组通过字符串的长度进行升序排序

var arr = ["asd","addasd","a","asdasd","asdasdadddddddd","d你好"]
arr.sort(function(a,b){
    return a.length - b.length
})

37.将下列arr数组通过字节进行升序排序

var arr = ["asd", "addasd", "a", "asdasd", "asdasdadddddddd", "d你好"]
function retBytes(str) {
    var length = str.length
    for (let i = 0; i < str.length; i++) {
        length += (str.charCodeAt(i) > 255) ? 1 : 0
    }
    return length
}
arr.sort(function (a, b) {
    return retBytes(a) - retBytes(b)
})

38.把下列字符串拼接到一起

var str = "alibaba",
    str1 = "baidu",
    str2 = "tencent",
    str3 = 'toutiao',
    str4 = 'wangyi';
// 方法一:这种写法不好,字符串实在栈内存里的,先进后出,
var arr = [str, str1, str2, str3, str4]
var strFinal = ''
for (var i = 0; i < arr.length; i++) {
    strFinal += arr[i]
}
// 方法二
var arr = [str, str1, str2, str3, str4]
var strFinal = arr.join("")

39.该代码运行后obj对象内部存储的数据为?

var obj = {
    "2":"a",
    "3":"b",
    "length":2,
    "push":Array.prototype.push
}
obj.push("c");  // 调用push方法,会在数组的最后(数组的长度)加上c,也就是第2位,即属性名为2的属性名变为c,添加完后length会+1,也就是length为3
obj.push("d");  // 调用push方法,会在数组的最后(数组的长度)加上d,也就是第3位,即属性名为3的属性名变为d,添加完后length会+1,也就是length为4
// 答案:var obj = { "2":"c",  "3":"d","length":4, "push":Array.prototype.push }

40.在数组的原型上实现数组去重方法

// 本方法是利用对象的特性(同一属性名不可以出现两次)来编写的一种方法
Array.prototype.unique = function () {
    var temp = {}, arr = []
    for (var i = 0; i < this.length; i++) {
        if (!temp[this[i]]) {
            temp[this[i]] = "abc";//这里最好随便赋值个字符串,不要写成temp[this[i]]=this[i],当数组有0时就有bug了
            arr.push(this[i])
        }
    }
    return arr
}
var arr = [1, 2, 3, 1, 2, 3, 4, 5, 6, 6]
var newArr = arr.unique()

41.写出以下打印信息

var name = "window";
var obj = {
    name:"obj",
    asy:function(){
        console.log(this.name)//”window“
    }
}
obj.say.call(window)//使用了call,call打破其他规则,使该方法中this指向window

42.尝试优化以下代码,使得代码看起来更优雅

// 
function getDay(day) {
    switch (day) {
        case 1: console.log("周一"); break;
        case 2: console.log("周二"); break;
        case 3: console.log("周三"); break;
        case 4: console.log("周四"); break;
        case 5: console.log("周五"); break;
        case 6: console.log("周六"); break;
        case 7: console.log("周日"); break;
        default: console.log("error")
    }
}
// 答案
function getDay(day) {
    var obj = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
    return (day <= obj.length && day > 0) ? obj[day - 1] : 'error'
}

43.一个字符串[a-z]组成,请找出该字符串第一个只出现一次的字母

var str = "skwdjfkjsdajsdkfjkdfqlkl"
function fun(str) {
    var arr = str.split("")
    for (var i = 0; i < arr.length; i++) {
        var num = 0
        for (var j = i + 1; j < arr.length; j++) {
            if (arr[i] == arr[j]) {
                num++;
            }
        }
        if (num == 0) return arr[i]
    }
}
console.log(fun(str))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值