本篇文章用于记录javaScript相关的一些题目,且长期更新,建议收藏!
1.使用原生js,通过addEventListener给每一个li元素绑定一个click事件,输出他们的顺序
js
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.写出以下打印信息
js
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时为中文)
js
function test(target) {
var count = target.length;
for (var i = 0; i < target.length; i++) {
if (target[i].charCodeAt() > 255) {
count++
}
}
return count
}
4.写出以下打印信息
js
// 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.写出以下打印信息
js
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的阶乘
js
//①抽象规律:n! = n * (n - 1)! ②出口:n为1时,为1
function factorial(n) {
if (n == 1) {
return 1;
}
return n * factorial(n - 1)
}
7.使用递归实现斐波那契数列
js
//①抽象规律: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.写出以下打印信息
js
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.写出以下打印信息
js
// 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.写出以下打印信息
js
// 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.写出以下打印信息
js
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]的选项是?
js
// 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.写出以下打印信息
js
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.写出以下打印信息
js
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.写出以下打印信息
js
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.请问以下表达式的结果是什么?
js
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的结果是什么?
js
function b(x, y, a) {
arguments[2] = 10;
alert(a);//10
}
b(1, 2, 3);
// 如果函数体改成下面,结果又会是什么?
a = 10;
alert(arguments[2]);//10
// 答案都是10,因为实参列表和形参是互相映射的,一个改了另一个也会跟着改。
18.写出以下打印信息
js
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.写出以下打印信息
js
var foo = '123';
function print() {
var foo = '456';
this.foo = '789';
console.log(foo);//456.会先在AO中找,找到foo为456,返回
}
print();
20.写出以下打印信息
js
var foo = '123';
function print() {
this.foo = '234';//print是在全局调用的,此时this会指向全局,所以会将全局的foo变成234
console.log(foo);//234,会先在AO中找,AO中没有,则沿着作用域链找,找到全局foo为234,返回
}
print();
21.写出以下打印信息
js
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()的结果分别是什么?
js
var a = 5;
function test() {
a = 0;
alert(a);//①0 ②0
alert(this.a);//5 ②undefined
var a;
alert(a)//①0 ②0
}
23.写出以下打印信息
js
function print() {
console.log(foo);//undefined
var foo = 2;
console.log(foo);//2
console.log(hello);//报错
}
print();
24.写出以下打印信息
js
function print() {
var test;
test();
function test() {
console.log(1);//1
}
}
print();
25.写出以下打印信息
js
function print(){
var x = 1;
if(x == '1')console.log("One!");//One!会尽量让两边相等,此时调用Number()将其都转为数字,所以相等,会打印
if(x === '1')console.log("Two!");//不不打印.===要完全相等才行
}
print();
26.写出以下打印信息
js
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.写出以下打印信息
js
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.写出以下打印信息
js
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.写出以下打印信息
js
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.写出以下打印信息
js
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?
js
// A
undefined == null;
// B
undefined === null;
// C
isNaN('100');//Number('100') = 100,是数字类型,不是NaN,所以为false
// D
parseInt('1a') == 1
// E
({}) == ({});//引用值比较的是地址,这是两个不同的对象,所以地址并不相等为false
// 答案是A、D