前端笔试做题笔记----JavaScript篇
- 1、this五种情况
- 2、({}+‘b‘>{}+‘a‘)返回值是() (考察 隐式类型转换)
- 3 、 js 函数定义方式
- 4、 js 单线程机制相关题目
- 5、变量提升和函数提升
- 6、 JavaScript 常见事件
- 7、 NOSCRIPT标签的作用
- 8、 JavaScript 数据类型那些事
- 9、立即执行函数
- 10、Array常用方法
- 11、String常用方法
- 12、Number常用方法
- 13、Math常用方法
- 14、Date常用方法
- 15、cookie、 localStorage、sessionStorage
- 16、JavaScript中bind、call和apply方法
- 17、代码分析
- 18、继承
1、this五种情况
- 当在函数调用的时候指向widow
- 当方法调用的时候指向调用对象
- 当用apply和call上下文调用的时候指向传入的第一个参数
- 构造函数调用指向实例对象
- 箭头函数中使用this指向该函数所在的作用域指向的对象
2、({}+‘b‘>{}+‘a‘)返回值是() (考察 隐式类型转换)
因为有比较运算符,且两边的数据类型都不同,所以隐式类型转换
{}+‘b’:
toPrimitive({},String)这里为什么是String,而不是Number。我是通过 {} + ‘b’ === “[object Object]b”//true验证的。
(ps:个人猜测因为都有字符串且是 + ,所以这里是转成String的原始值)
{}.valueOf();//{}空对象
{}.toString();//“[object,object]”
toPrimitive(“[object,object]”,String)所以{}隐式类型转换的原始值为String(“[object,object]”);//“[object,object]”
所以:{}+‘b’ ==>“[object,object]”+‘b’
{}+'a’同理
因此最后{}+‘b’>{}+‘a’ ==> “[object,object]b” > “[object,object]a”;
为了验证是这样:console.log({}+‘2’>{}+‘3’);//false;
3 、 js 函数定义方式
- 函数声明语法定义:
function sum(num1,num2){return num1+num2} - 函数表达式定义函数:
var sum = function(num1,num2){return num1+num2};-
var sum = new Function("num1","num2","return num1+num2");Function构造函数可以接受任意数量的参数,但最后一个参数始终被看成函数体,注意函数表达式定义函数的方法与声明其他变量时一样需要加分号。
4、 js 单线程机制相关题目
var声明的变量i不具有块级作用域
- 异步任务–点击事件
这里考的是JS的运行机制! 事件(click,focus等等),定时器(setTimeout和setInterval),ajax,都是会触发异步,属于异步任务;js是单线程的,一个时间点只能做一件事,优先处理同步任务; 按照代码从上往下执行,遇到异步,就挂起,放到异步任务里,继续执行同步任务,只有同步任务执行完了,才去看看有没有异步任务,然后再按照顺序执行! 这里for循环是同步任务,onclick是异步任务,所以等for循环执行完了,i变成4了,注意:这里因为i是全局变量,最后一个i++,使得i为4(后面的onclick函数,最后在循环外面执行,不受i<length限制); 所以for循环每执行一次,onclick事件函数都会被挂起一次,共4次; for循环结束后,点击事件 触发了4个onclick函数,接着输出4个4!
- 异步任务–定时器 (let和var)
第一个:let将i绑定到for循环快中,事实上它将其重新绑定到循环体的每一次迭代中,确保上一次迭代结束的值重新被赋值。setTimeout里面的function()属于一个新的域,通过 var 定义的变量是无法传入到这个函数执行域中的,通过使用 let 来声明块变量,这时候变量就能作用于这个块,所以 function就能使用 i 这个变量了;输出为0,1.
第二个:settimeout是异步执行,1s后往异步任务队列里面添加一个任务,只有同步的全部执行完,才会执行异步任务队列里的任务,当主线执行完成后,i是2,所以此时再去执行任务队列里的任务时,所以输出两次2.
5、变量提升和函数提升
- 函数声明提升优先级高于变量声明提升
当变量和函数同名时,优先留下函数的值,即函数的优先级更高
- 提升就是声明(变量/函数)提至当前作用域的最顶部,赋值语句留在原地
//原来的代码
var a = 2;
function fn(){
b();
return ;
var a = 1;
function b(){
console.log(a);
}
}
fn();
//实际上的代码
var a = 2;
function fn(){
function b(){
console.log(a);
}
var a //变量声明提升,默认赋值为undefined
b(); //执行函数b,在当前作用域找到a,值为undefined
return;//return后面的语句不再执行,a没有被赋值为1
a = 1; //在原来的位置才会赋值,但不会执行到这里
}
fn();- 函数创建有3个形式,函数声明和函数表达式( 以及 new Function构造函数),只有函数声明才有函数提升
//函数声明
function f1(){
console.log('我是函数声明')
}
//函数表达式
var f2 = function () {
console.log('我是函数表达式')
}
函数发生提升后
// 函数声明--提升
function f1() {
console.log('我是函数声明')
}
var f2;
f1() //'我是函数声明'
f2() //error:f2 is not a function
// 函数表达式
f2 = function() {
console.log('我是函数表达式')
}6、 JavaScript 常见事件
- 鼠标事件
- 键盘事件
- 焦点事件
- 滚轮事件
7、 NOSCRIPT标签的作用
NOSCRIPT标签用来定义在脚本未被执行时的替代内容。也可以用在检测浏览器是否支持脚本,若不支持脚本则可以显示NOSCRIPT标签里的innerText
noscript:用以在不支持js的浏览器中显示替代的内容,这个元素可以包含能够出现在文档中任何html元素,script元素除外。包含在noscript元素的内容只有在下列情况下才会显示出来
- 浏览器不支持脚本
- 浏览器支持脚本,但脚本被禁用
8、 JavaScript 数据类型那些事
- undefined和null与任何有意义的值比较返回的都是false,但是null与undefined之间互相比较返回的是true。
- Symbol类型
- Symbol为ES6新增的基本数据类型,表示独一无二的值。
- Symbol()函数会返回symbol类型的值,每个从Symbol()返回的symbol值都是唯一的。
- Symbol.for() 返回由给定的 key 找到的 symbol,否则就是返回新创建的 symbol
- 用Symbol来创建Symbol对象时,不使用new运算符
- NaN==NaN为假,NaN是一个不确定数,所以NaN不能等于NaN
- null instanceof Object为假,在js中 typeof null会返回object,这并不意味着null是object类型,只是遗留错误。null不是object创建的实例对象
9、立即执行函数

答案:E
function() {output(“Hello World!”)})()匿名的立即执行函数
1.先立即执行匿名函数,输出Hello World! 2.函数执行后无返回值,则输出未定义
10、Array常用方法
indexOf()搜索数组中的元素,并返回它所在的位置。
var fruits = ["Banana", "Orange", "Apple", "Mango"];
var a = fruits.indexOf("Apple");
//输出
2includes()判断一个数组是否包含一个指定的值。
let site = ['runoob', 'google', 'taobao'];
site.includes('runoob');
// true
site.includes('baidu');
// false
arr.includes(searchElement, fromIndex)
//searchElement 必须。需要查找的元素值。
//fromIndex 可选。从该索引处开始查找 searchElement。如果为负值,则按升序从 array.length + fromIndex 的索引开始搜索。默认为 0。
//如果 fromIndex 为负值,计算出的索引将作为开始搜索searchElement的位置。如果计算出的索引小于 0,则整个数组都会被搜索。
var arr = ['a', 'b', 'c'];
arr.includes('a', -100); // true
arr.includes('b', -100); // true
arr.includes('c', -100); // trueconcat()连接两个或更多的数组,并返回结果。
var hege = ["Cecilie", "Lone"];
var stale = ["Emil", "Tobias", "Linus"];
var kai = ["Robin"];
var children = hege.concat(stale,kai);
//children 输出结果:
Cecilie,Lone,Emil,Tobias,Linus,Robin-
reduce()将数组元素计算为一个值(从左到右)。 -
some()检测数组元素中是否有元素符合指定条件。
some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。
some() 方法会依次执行数组的每个元素:
如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。
如果没有满足条件的元素,则返回false。
注意: some() 不会对空数组进行检测。
注意: some() 不会改变原始数组。
-
find()返回符合传入测试(函数)条件的数组元素。
find() 方法返回通过测试(函数内判断)的数组的第一个元素的值。
find() 方法为数组中的每个元素都调用一次函数执行:
当数组中的元素在测试条件时返回 true 时, find() 返回符合条件的元素,之后的值不会再调用执行函数。
如果没有符合条件的元素返回 undefined
注意: find() 对于空数组,函数是不会执行的。
注意: find() 并没有改变数组的原始值。
filter()检测数值元素,并返回符合条件所有元素的数组。
//filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
//注意: filter() 不会对空数组进行检测。
//注意: filter() 不会改变原始数组。
var ages = [32, 33, 16, 40];
function checkAdult(age) {
return age >= 18;
}
function myFunction() {
document.getElementById("demo").innerHTML = ages.filter(checkAdult);
}
//输出结果为:
32,33,40-
every()检测数值元素的每个元素是否都符合条件。
every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
every() 方法使用指定函数检测数组中的所有元素:
如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
如果所有元素都满足条件,则返回 true。
注意: every() 不会对空数组进行检测。
注意: every() 不会改变原始数组。
unshift()向数组的开头添加一个或更多元素,并返回新的长度。##### 11、String常用方法
//unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。
//注意: 该方法将改变数组的数目。
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.unshift("Lemon","Pineapple");
//输出:
Lemon,Pineapple,Banana,Orange,Apple,Mangopush()将新项目添加到数组的末尾
const fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.push("Kiwi");
document.getElementById("demo").innerHTML = fruits;
//输出:
Banana,Orange,Apple,Mango,Kiwislice()选取数组的一部分,并返回一个新数组。
//slice() 方法可从已有的数组中返回选定的元素。
//slice()方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。
//注意: slice() 方法不会改变原始数组。
var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
var citrus = fruits.slice(1,3);
//输出:
Orange,LemonforEach()数组每个元素都执行一次回调函数。
//forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。
//注意: forEach() 不会改变原数组
//注意: forEach() 对于空数组是不会执行回调函数的。
var arr = [1, 2, 3, 4, 5];
arr.forEach(function (item) {
if (item === 3) {
return;
}
console.log(item);
});-
isArray()判断对象是否为数组,isArray() 方法用于判断一个对象是否为数组。
如果对象是数组返回 true,否则返回 false。
11、String常用方法
-
includes()查找字符串中是否包含指定的子字符串。 -
concat()连接两个或更多字符串,并返回新的字符串。 -
indexOf()返回某个指定的字符串值在字符串中首次出现的位置。 replace()在字符串中查找匹配的子串, 并替换与正则表达式匹配的子串。
//replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
//如果想了解更多正则表达式教程请查看本站的:RegExp 教程 和 our RegExp 对象参考手册.
//该方法不会改变原始字符串。
var str="Visit Microsoft! Visit Microsoft!";
var n=str.replace("Microsoft","Runoob");
// 输出结果:
Visit Runoob!Visit Microsoft!-
slice()提取字符串的片断,并在新的字符串中返回被提取的部分。 split()把字符串分割为字符串数组。
//split() 方法用于把一个字符串分割成字符串数组。
//提示: 如果把空字符串 ("") 用作 separator,那么 stringObject 中的每个字符之间都会被分割。
//注意: split() 方法不改变原始字符串。
var str="How are you doing today?";
var n=str.split(" ");
//输出一个数组的值:
How,are,you,doing,today?substr()从起始索引号提取字符串中指定数目的字符。
var str="Hello world!";
var n=str.substr(2,3)
// 输出结果:
llo-
substring()提取字符串中两个指定的索引号之间的字符。 trim()去除字符串两边的空白
var str = " Runoob ";
alert(str.trim());
//输出结果:
RunoobtoString()返回一个字符串。
var str = "Runoob";
var res = str.toString();
//输出结果:
Runoob12、Number常用方法
valueOf()返回一个 Number 对象的基本数字值。
//返回一个 Number 对象的基本数字值:
var num = 15;
var n = num.valueOf();
//输出结果:
15toFixed()把数字转换为字符串,结果的小数点后有指定位数的数字。
//把数字转换为字符串,结果的小数点后有指定位数的数字:
var num = 5.56789;
var n=num.toFixed(2);
//输出结果:
5.5713、Math常用方法
random()返回 0 ~ 1 之间的随机数。
//返回介于 0(包含) ~ 1(不包含) 之间的一个随机数:
Math.random();
//输出结果:
0.13704677732303505round(x)四舍五入。
//round() 方法可把一个数字舍入为最接近的整数:
Math.round(2.5);
//输出结果:
3floor(x)对 x 进行下舍入。
//返回小于等于x的最大整数:
Math.floor(1.6);
//以上实例将输出:
1ceil(x)对x进行上舍入。
//对一个数进行上舍入:
Math.ceil(1.4)
//输出结果:
214、Date常用方法
getDate()从 Date 对象返回一个月中的某一天 (1 ~ 31)。
var d = new Date();
var n = d.getDate();
//输出结果:
6-
getDay()从 Date 对象返回一周中的某一天 (0 ~ 6)。 -
getFullYear()从 Date 对象以四位数字返回年份。 -
getHours()返回 Date 对象的小时 (0 ~ 23)。 -
getMinutes()返回 Date 对象的分钟 (0 ~ 59)。 -
getMonth()从 Date 对象返回月份 (0 ~ 11)。 -
getSeconds()返回 Date 对象的秒数 (0 ~ 59)。 setDate()设置 Date 对象中月的某一天 (1 ~ 31)。
var d = new Date();
d.setDate(15);
//输出结果:
Thu Apr 15 2021 11:27:56 GMT+0800 (中国标准时间)-
setFullYear()设置 Date 对象中的年份(四位数字)。 -
setHours()设置 Date 对象中的小时 (0 ~ 23)。 -
setMinutes()设置 Date 对象中的分钟 (0 ~ 59)。 -
setMonth()设置 Date 对象中月份 (0 ~ 11)。
15、cookie、 localStorage、sessionStorage

16、JavaScript中bind、call和apply方法
- call()、apply()、bind() 都是用来重定义 this 这个对象的
- 以上出了 bind 方法后面多了个 () 外 ,结果返回都一致!
由此得出结论,bind 返回的是一个新的函数,你必须调用它才会被执行。 - 对比call 、bind 、 apply 传参情况下
- 微妙的差距!
从上面四个结果不难看出:
call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,第二个参数差别就来了:
call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面obj.myFun.call(db,'成都', ... ,'string' )。
apply 的所有参数都必须放在一个数组里面传进去obj.myFun.apply(db,['成都', ..., 'string' ])。
bind 除了返回是函数以外,它 的参数和 call 一样。
当然,三者的参数不限定是 string 类型,允许是各种类型,包括函数 、 object 等等!


17、代码分析
- 分析如下代码打印出的结果
var foo = {n:1};
(function(foo){
console.log(foo.n);
foo.n = 3;
var foo = {n:2};
console.log(foo.n);
})(foo);
console.log(foo.n);解析:
var foo = {n:1};
(function(foo){ //形参foo同实参foo一样指向同一片内存空间,这个空间里的n的值为1
var foo; //优先级低于形参,无效。
console.log(foo.n); //输出1
foo.n = 3; //形参与实参foo指向的内存空间里的n的值被改为3
foo = {n:2}; //形参foo指向了新的内存空间,里面n的值为2.
console.log(foo.n); //输出新的内存空间的n的值
})(foo);
console.log(foo.n); //实参foo的指向还是原来的内存空间,里面的n的值为3.- 分析如下代码打印的结果为
var a = 4399 < 0 || typeof(4399 + '');
console.log(a);解析:
&&运算,如果前面值为true,则结果为后面的值。如果前面值为false,则值为false.
||运算,如果前面值为true,则结果为前面的值,如果前面的值为false,则结果为后面的值。
18、继承
- 原型继承
function Animal(){
this.type = '动物'
}
function Cat(name,color){
= name;
this.color = color
}
Cat.prototype = new Animal()
var c1 = new Cat('x','白色')
var c2 = new Cat('f','花色')
console.log(c1)
console.log(c2)优点:同一个原型对象
缺点:不能修改原型对象,会影响所有实例
- 构造函数的继承
function Animal(){
this.type = '动物'
}
function Cat(name,color){
Animal.apply(this) //将Animal对象的成员赋值到Cat对象上
= name;
this.color = color
}
var c1 = new Cat('x','白色')
var c2 = new Cat('f','花色')
console.log(c1)
console.log(c2)优点:不存在需修改原型对象影响所有实例,各自拥有独立属性
缺点:父类的成员会被创建多次,存在冗余且不是同一个原型对象
通过apply/call只能拷贝成员,原型对象并不会拷贝
- 组合继承
function Animal(){
this.type = '动物'
}
Animal.prototype.eat = function(){console.log('吃吃')}
function Cat(name,color){
Animal.apply(this) //将Animal对象的成员赋值到Cat对象上
= name;
this.color = color
}
Cat.prototype = new Animal()
var c1 = new Cat('x','白色')
var c2 = new Cat('f','花色')
c1.type = '我是x' //修改当前构造器中的属性
c2.__proto__.type='我是动物' //修改原型对象的值,但 不影响c1、c2的值
console.log(c1.type)
console.log(c2.type)
console.log(c1.__proto__.type)
console.log(c2.__proto__.type)持续更新中…
















