延迟加载:async、defer
例如:defer : 等html全部解析完成,才会执行js代码,顺次执行js脚本。
async : async是和html解析同步的(一起的),不是顺次执行js脚本(谁先加载完谁先执行)。
基本类型:string、number、boolean、undefined、null、symbol、bigint
引用类型:object
NaN是一个数值类型,但是不是一个具体的数字。
三、JS数据类型考题 考题一:console.log( true + 1 ); //2
console.log( 'name'+true ); //nametrue
console.log( undefined + 1 ); //NaN
console.log( typeof undefined ); //undefined
考题二:
console.log( typeof(NaN) ); //number
console.log( typeof(null) ); //object
四、null和undefined的区别
1. 作者在设计js的都是先设计的null(为什么设计了null:最初设计js的时候借鉴了java的语言)
2. null会被隐式转换成0,很不容易发现错误。
3. 先有null后有undefined,出来undefined是为了填补之前的坑。
具体区别:JavaScript的最初版本是这样区分的:null是一个表示"无"的对象(空对象指针),转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。
五、==和===有什么不同?六、JS微任务和宏任务== : 比较的是值
string == number || boolean || number ....都会隐式转换
通过valueOf转换(valueOf() 方法通常由 JavaScript 在后台自动调用,并不显式地出现在代码中。)=== : 除了比较值,还比较类型
1. js是单线程的语言。
2. js代码执行流程:同步执行完==》事件循环
同步的任务都执行完了,才会执行事件循环的内容
进入事件循环:请求、定时器、事件....
3. 事件循环中包含:【微任务、宏任务】
微任务:promise.then
宏任务:setTimeout..
要执行宏任务的前提是清空了所有的微任务
流程:同步==》事件循环【微任务和宏任务】==》微任务==》宏任务=》微任务...
七、JS作用域考题考题一:1. 除了函数外,js是没有块级作用域。
2. 作用域链:内部可以访问外部的变量,但是外部不能访问内部的变量。
注意:如果内部有,优先查找到内部,如果内部没有就查找外部的。
3. 注意声明变量是用var还是没有写(window.)
4. 注意:js有变量提升的机制【变量悬挂声明】
5. 优先级:声明变量 > 声明普通函数 > 参数 > 变量提升
function c(){
var b = 1;
function a(){
console.log( b );
var b = 2;
console.log( b );
}
a();
console.log( b );
}
c();
考题二:
var name = 'a';
(function(){
if( typeof name == 'undefined' ){
var name = 'b';
console.log('111'+name);
}else{
console.log('222'+name);
}
})()
考题三:
function fun( a ){
var a = 10;
function a(){}
console.log( a );
}
fun( 100 );
八、JS对象考题
JS对象注意点:
考题一:1. 对象是通过new *** 作符构建出来的,所以对象之间不想等(除了引用外);
2. 对象注意:引用类型(共同一个地址);
3. 对象的key都是字符串类型;
4. 对象如何找属性|方法;
查找规则:先在对象本身找 ===> 构造函数中找 ===> 对象原型中找 ===> 构造函数原型中找 ===> 对象上一层原型查找
[1,2,3] === [1,2,3] //false
考题二:
var obj1 = {
a:'hellow'
}
var obj2 = obj1;
obj2.a = 'world';
console.log(obj1); //{a:world}
(function(){
console.log(a); //undefined
var a = 1;
})();
考题三:
var a = {}
var b = {
key:'a'
}
var c = {
key:'c'
}
a[b] = '123';
a[c] = '456';
console.log( a[b] ); // 456
九、JS作用域+this指向+原型的考题
考题一:
function Foo(){
getName = function(){console.log(1)} //注意是全局的window.
return this;
}
Foo.getName = function(){console.log(2)}
Foo.prototype.getName = function(){console.log(3)}
var getName = function(){console.log(4)}
function getName(){
console.log(5)
}
Foo.getName(); //2
getName(); //4
Foo().getName(); //1
getName(); //1
new Foo().getName();//3
考题二:
var o = {
a:10,
b:{
a:2,
fn:function(){
console.log( this.a ); // 2
console.log( this ); //代表b对象
}
}
}
o.b.fn();
考题三:
window.name = 'ByteDance';
function A(){
this.name = 123;
}
A.prototype.getA = function(){
console.log( this );
return this.name + 1;
}
let a = new A();
let funcA = a.getA;
funcA(); //this代表window
考题四:
var length = 10;
function fn(){
return this.length + 1;
}
var obj = {
length:5,
test1:function(){
return fn();
}
}
obj.test2 = fn;
console.log( obj.test1() ); //1
console.log( fn()===obj.test2() ); //false
console.log( obj.test1() == obj.test2() ); //false
十、JS判断变量是不是数组,你能写出哪些方法?
方式一:isArray
var arr = [1,2,3];
console.log( Array.isArray( arr ) );
方式二:instanceof 【可写,可不写】
var arr = [1,2,3];
console.log( arr instanceof Array );
方式三:原型prototype
var arr = [1,2,3];
console.log( Object.prototype.toString.call(arr).indexOf('Array') > -1 );
方式四:isPrototypeOf()
var arr = [1,2,3];
console.log( Array.prototype.isPrototypeOf(arr) )
方式五:constructor
var arr = [1,2,3];
console.log( arr.constructor.toString().indexOf('Array') > -1 )
十一、slice是干嘛的、splice是否会改变原数组
1. slice是来截取的
参数可以写slice(3)、slice(1,3)、slice(-3)返回的是一个新的数组2. splice 功能有:插入、删除、替换
返回:删除的元素该方法会改变原数组 十二、JS数组去重 方式一:new setvar arr1 = [1,2,3,2,4,1];
function unique(arr){
return [...new Set(arr)]
}
console.log( unique(arr1) );
方式二:indexOf
var arr2 = [1,2,3,2,4,1];
function unique( arr ){
var brr = [];
for( var i=0;i
方式三:sort
var arr3 = [1,2,3,2,4,1];
function unique( arr ){
arr = arr.sort();
var brr = [];
for(var i=0;i
十三、找出多维数组最大值
function fnArr(arr){
var newArr = [];
arr.forEach((item,index)=>{
newArr.push( Math.max(...item) )
})
return newArr;
}
console.log(fnArr([
[4,5,1,3],
[13,27,18,26],
[32,35,37,39],
[1000,1001,857,1]
]));
十四、给字符串新增方法实现功能
给字符串对象定义一个addPrefix函数,当传入一个字符串str时,它会返回新的带有指定前缀的字符串,例如:
console.log( 'world'.addPrefix('hello') ) 控制台会输出helloworld
String.prototype.addPrefix = function(str){
return str + this;
}
console.log( 'world'.addPrefix('hello') )
十五、找出字符串出现最多次数的字符以及次数
var str = 'aaasdwqeasdaqwd';
var o = {};
for (var i = 0; i < str.length; i++) {
var index = str[i];
if (!o[index]) {
o[index] = 1;
} else {
o[index]++;
}
}
var max = 0;
var str1 = '';
for (var k in o) {
if (o[k] > max) {
max = o[k];
str1 = k;
}
}
console.log('出现最多的次数:' + max + '及其字母为:' + str1);
十六、new *** 作符具体做了什么
在内存中创建一个新的空对象。让 this 指向这个新的对象。执行构造函数里面的代码,给这个新对象添加属性和方法返回这个新对象(所以构造函数里面不需要return)
十七、闭包
1. 闭包是什么
闭包是一个函数加上到创建函数的作用域的连接,闭包“关闭”了函数的自由变量。
优点:1.可以访问到函数内部的局部变量,
2.可以避免全局变量的污染,
3.这些变量的值始终保持在内存中,不会在外层函数调用后被自动清除。
缺点:会增大内存使用量,滥用闭包会影响性能,导致内存泄漏【如果说一定要提到ie】等问题。
解决方法:在退出函数之前,将不使用的局部变量全部删除,可以使变量赋值为null。
十八、原型链1. 原型可以解决什么问题
对象共享属性和共享方法2. 谁有原型
函数拥有:prototype对象拥有:__proto__3. 对象查找属性或者方法的顺序
先在对象本身查找 --> 构造函数中查找 --> 对象的原型 --> 构造函数的原型中 --> 当前原型的原型中查找4. 原型链
4.1 是什么?:就是把原型串联起来
4.2 原型链的最顶端是null
class Parent{
constructor(){
this.age = 18;
}
}
class Child extends Parent{
constructor(){
super();
this.name = '张三';
}
}
let o1 = new Child();
console.log( o1,o1.name,o1.age );
方式二:原型链继承
function Parent(){
this.age = 20;
}
function Child(){
this.name = '张三'
}
Child.prototype = new Parent();
let o2 = new Child();
console.log( o2,o2.name,o2.age );
方式三:借用构造函数继承
function Parent(){
this.age = 22;
}
function Child(){
this.name = '张三'
Parent.call(this);
}
let o3 = new Child();
console.log( o3,o3.name,o3.age );
方式四:组合式继承
function Parent(){
this.age = 100;
}
function Child(){
Parent.call(this);
this.name = '张三'
}
Child.prototype = new Parent();
let o4 = new Child();
console.log( o4,o4.name,o4.age );
二十、call、apply、bind区别
共同点:功能一致
可以改变this指向
语法: 函数.call()、函数.apply()、函数.bind()
区别:
1. call、apply可以立即执行。bind不会立即执行,因为bind返回的是一个函数需要加入()执行。2. 参数不同:apply第二个参数是数组。call和bind有多个参数需要挨个写。场景:
1. 用apply的情况
var arr1 = [1,2,4,5,7,3,321];
console.log( Math.max.apply(null,arr1) )
2. 用bind的情况
var btn = document.getElementById('btn');
var h1s = document.getElementById('h1s');
btn.onclick = function(){
console.log( this.id );
}.bind(h1s)
二十一、sort背后原理是什么?
V8 引擎 sort 函数只给出了两种排序 InsertionSort 和 QuickSort,数量小于10的数组使用 InsertionSort,比10大的数组则使用 QuickSort。
之前的版本是:插入排序和快排,现在是冒泡
原理实现链接:https://github.com/v8/v8/blob/ad82a40509c5b5b4680d4299c8f08d6c6d31af3c/src/js/array.js
***710行代码开始***
二十二、深拷贝和浅拷贝共同点:复制
1. 浅拷贝:只复制引用,而未复制真正的值。
var arr1 = ['a','b','c','d'];
var arr2 = arr1;
var obj1 = {a:1,b:2}
var obj2 = Object.assign(obj1);
2. 深拷贝:是复制真正的值 (不同引用)
var obj3 = {
a:1,
b:2
}
var obj4 = JSON.parse(JSON.stringify( obj3 ));
//递归的形式
var oldObj = {
a: 1,
b: 2,
arr: ['1', '2', '3']
};
var newObj = {};
function recursion(newObj, oldObj) {
for (var k in oldObj) {
var item = oldObj[k];
if (item instanceof Array) {
newObj[k] = [];
recursion(newObj[k], item);
} else if (item instanceof Object) {
newObj[k] = {};
recursion(newObj[k], item);
} else {
newObj[k] = item;
}
}
return newObj;
}
recursion(newObj, oldObj);
newObj.a = '我是你爸爸真伟大'
console.log(newObj);
console.log(oldObj);
二十三、localStorage、sessionStorage、cookie的区别
公共点:在客户端存放数据
区别:
1. 数据存放有效期
sessionStorage : 仅在当前浏览器窗口关闭之前有效。【关闭浏览器就没了】localStorage : 始终有效,窗口或者浏览器关闭也一直保存,所以叫持久化存储。cookie : 只在设置的cookie过期时间之前有效,即使窗口或者浏览器关闭也有效。2. localStorage、sessionStorage不可以设置过期时间
cookie 有过期时间,可以设置过期(把时间调整到之前的时间,就过期了)3. 存储大小的限制
cookie存储量不能超过4klocalStorage、sessionStorage不能超过5M****根据不同的浏览器存储的大小是不同的。
二十四、http状态码的了解 2开头的表示请求成功 200表示一切正常3开头的表示重定向 301永久重定向302临时重定向4开头表示客户端错误 400表示请求报文中存在语法错误403常见的跨域404请求资源不存在5开头表示服务器端错误 500表明服务器端在执行请求时发生了错误 二十五、防抖和节流的作用二十六、var、let、const区别防抖:高频的触发事件,规定时间内触发会被清除,只有当超过规定时间触发,然后执行最后一次事件
节流:高频的触发事件,限制触发次数,规定时间内只能触发一次
var、let、const 共同点都是可以声明变量的
区别一:
var 具有变量提升的机制 let和const没有变量提升的机制区别二:
var 可以多次声明同一个变量 let和const不可以多次声明同一个变量区别三:
var、let声明变量的 const声明常量 var和let声明的变量可以再次赋值,但是const不可以再次赋值了。区别四:
var声明的变量没有自身作用域 let和const声明的变量有自身的作用域 二十七、作用域考题考题一:let和const没有变量提升性
console.log( str );//undefined
var str = '你好';
console.log( num );//报错
let num = 10;
考题二:
function demo(){
var n = 2;
if( true ){
var n = 1;
}
console.log( n );//1
}
demo();
function demo(){
let n = 2;
if( true ){
let n = 1;
}
console.log( n );//2
}
demo();
考题三:可以修改
const obj = {
a:1
}
obj.a = 11111;
console.log( obj )
const arr = ['a','b','c'];
arr[0]= 'aaaaa';
console.log( arr );
二十八、将下列对象进行合并
方式一:Object.assign
const a = {a:1,b:4};
const b = {b:2,c:3};
let obj1 = Object.assign(a,b);
console.log( obj1 );
方式二:...
let obj2 = {...a,...b};
console.log( obj2 );
方式三:自己封装方法
function extend( target, source ){
for(var key in source){
target[key] = source[key];
}
return target;
}
console.log( extend(a,b) );
二十九、箭头函数和普通函数有什么区别?
1. this指向的问题
箭头函数中的this只在箭头函数定义时就决定的,而且不可修改的(call、apply、bind)****箭头函数的this指向定义时候、外层第一个普通函数的this2. 箭头函数不能new(不能当作构造函数)
3. 箭头函数prototype
4. 箭头函数arguments
有三种状态:
pending(进行中)fulfilled(已成功)rejected(已失败) 三十一、find和filter的区别区别一:返回的内容不同
filter 返回是新数组find 返回具体的内容区别二:
find 匹配到第一个即返回filter 返回整体(没一个匹配到的都返回) 三十二、some和every的区别 some 如果有一项匹配则返回trueevery 全部匹配才会返回true欢迎分享,转载请注明来源:内存溢出
评论列表(0条)