第一题
<script> var a = 10; function test() { a = 100; console.log(a); //100 console.log(this.a) //10 var a; console.log(a) //100 } test() // 解题思路 : 变量提升 函数调用模式的this指向window </script>
第二题
<script> for(var i=1; i<10; i++){ setTimeout(function(){ console.log(i) },1000) } // 输出9遍 10
for(let i=1; i<10; i++){ setTimeout(function(){ console.log(i) },1000) } // 输出 1,2,3,4,5,6,7,8,9 </script>
第三题
<script> // 输出结果? var arr = [1,3,4,5,65,6] arr.forEach( i=>{ console.log(i); if(i==5){ return } }) // 输出结果 1,3,4,5,65,6 </script>
第四题
第五题
<script> // 已知有以下数组,请将数组随机乱序 let arr = [1,2,3,4,5] // 方法一 let newArr=[] for(let i = 0; i < Infinity; i++){ if(newArr.length==5){// 如果 newArr 和 arr原始数组的长度一样,跳出循环 break } let index = Math.floor( Math.random() * arr.length ) //随机获取数组下标 newArr.push(arr[index]) // 将随机出来的元素添加到newArr中 arr.splice(index,1) //删除添加过的元素 } console.log(newArr) </script>
<script> // 已知有以下数组,请将数组随机乱序 let arr = [1,2,3,4,5] // 方法二 let newArr=[] for(let i = 0; i < arr.length; i++){ let index = Math.floor( Math.random() * arr.length ) //随机获取数组下标 newArr.push(arr[index]) // 将随机出来的元素添加到newArr中 arr.splice(index,1) //删除添加过的元素 } var result = new Set( [ ...arr , ...newArr ] ) console.log([...result]) </script>
第六题
npm init 和 npm install vue 区别? 如何安装指定版本的js模块? npm init 是初始化项目,使用后会多出一个 package.json 的文件 npm install vue 是安装vue 使用 @ 可以指定版本 比如: npm i jquery@3.0.0 全局安装? npm install xxx -g //模块将被下载安装到【全局目录】中 本地安装? npm install xxx //则是将模块下载到当前命令行所在目录 信息写入?(安装的同时,将信息写入package.json中项目路径中) npm install xxx --save npm install xxx --save-dev --save 将依赖包名称添加到 package.json 文件 dependencies 键下 (发布后依赖的东西) --save-dev 则添加到 package.json 文件 devDependencies 键下 (开房时候依赖的东西) --save 是你发布之后还依赖的东西 --save-dev 是你开发时候依赖的东西
第七题
如何实现单页面同时适应 pc 和 移动端设备 ?
@media 媒体查询 /* 当屏幕小于等于100px的时候背景色为红色 */ @media screen and (max- 100px) { .example {background: red;} } /* 当屏幕在 200px -- 300px 的时候背景色为绿色 */ @media screen and (min- 200px) and (max- 300px) { .example {background: green;} } 或者使用bootstrap中的媒体查询
第八题
vue中如何防止卡白屏?
原因? vue项目完成后一打包,js都放到了一起,由于js太庞大,加载变慢出现白屏(app.js太大)
解决?
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
使用路由懒加载,可以将js分别打包到不同的文件中。
使用骨架屏(vant)
01 配置打包工具,将组件分别打包到不同的js代码块中
biuld/weabpack.base.conf.js
output:{
chunkFilename:"[ ]" //为了懒加载新增,配置后webpack将打包出多个js文件
}
02 当路由请求到该组件时,才动态加载组件的内容
引入组件时要改为
import index from './'xxx 改为 const index=()=>import ('./xxx') 仅定义函数 不执行
当用户在vue中请求当前组件对应的路由地址时,由vue-router自动调用加载函数
第九题
简单描述一下前端优化的理解?
css放顶部,js放底部
精灵图,字体图标
压缩代码
前端你的优化在于减少DOM的操作和减少页面的重排重绘
第十题
call和apply的区别是什么?哪个性能更好一点?
call传参是一个一个传入 fn.call( obj , 10,20,30)
apply传参要用数组的形式[ ] fn.apply( obj , [10,20,30] )
传参多的时候,call的性能要比apply稍好些。所以call的性能要优于apply,所以在开发时候,使用call,如果传入的参数是数组,可以使用...展开用算符传参 fn.call( obj , ...arry )
第十一题
代码性能测试 console.time('a') console.timeEnd('a')
<script> // 测试代码运行时间可以使用 console.time和console.timeEnd 来测试一段代码运行的时间 console.time('A') for( let i=1 ; i<100; i++){ } console.timeEnd('A') // 输出结果: A: 0.007080078125ms </script>
第十二题
实现 (5).add(3).minus(2) ,使其结果输出为6
<script> /* arr.push() arr数组之所以可以调用数组方法, 是因为 arr是Array的实例,可以调用Array.prototype 原型上的方法。push就是Array的方法 jq源码中:给原型上添加方法 ['add','minus'].forEach( elem=>{ Number.prototype[elem] = eval(elem) }) */ // 5 + 3 - 2 = 6 // 实现 (5).add(3).minus(2) ,使其结果输出为6 (function(){ function check(n) { n = Number(n) return isNaN(n) ? 0 : n ; // 如果是NAN返回0 否则返回n } // 每一个方法执行完,都要返回Number这个类的实例,这样才可以继续调用Number类原型中的方法(链式写法) function add(n=0){ n = check(n) return this + n; //this指向5 ; } function minus(n=0){ n = check(n) return this - n; } Number.prototype.add=add; //将add函数添加到原型中 Number.prototype.minus=minus;//将minus函数添加到原型中 }()); console.log( (5).add(3).minus(2) ) // 6 </script>
十三题
什么是回调函数:把一个函数B作为实参传递给另外一个函数A;函数A在执行的时候,可以把传递进来的函数B去执行(执行N次数)
function each(arr,callBack) { for( let i= 0; i < arr.length; i++){ let item = arr[i]; index = i; callBack( item , index ) } } each( [1,2,3,4], function( item, index) { } )
十四题
箭头函数和普通函数的区别是什么? 构造函数可以使用new生成实例,那么箭头函数可以吗?为什么? 箭头函数和普通函数的区别? 01 箭头函数语法上比普通函数更简洁 02 箭头函数没有自己的this,它里面的this继承函数所处上下文中的this(箭头函数中的this与外层函数的this一致) 箭头函数中的this,使用call/apply等任何方式都无法改变this的指向(都和外层函数this一致) 03 箭头函数中没有 arguments(类数组) 04 箭头函数不能被new执行(普通函数 可以写成构造函数格式),为什么?因为箭头函数中没有this,箭头函数没有prototype 箭头函数时没有this,也没有prototype,也没有arguments
十五题
console.log(a) //undefined var a = 12; function fn () { console.log(a); // 12 a = 13; } fn(); console.log(a); //13
十六题
axios和ajax的区别?
axios是基于promise的专门发送ajax请求的函数库,通过promise实现对ajax的封装。自动转换JSON数据
ajax是针对mvc的编程,不符合mvvm模式的开发
$.ajax({ url: '/getUsers', type: 'get', dataType: 'json', data: { //'a': 1, //'b': 2, }, success: function (response) { console.log(response); } })
<script> axios.get("url",{ params:{ 请求参数: 参数值 } }).then(function(返回结果result){ result.data //才是服务器返回的结果 }) // 比如: 用id查询一个商品 //http://localhost:3000/products/getById?lid=5 -> // { lid:5, title: macbook, subtitle: 优惠酬宾, ... } <- axios.get("/products/getById",{ params:{ lid:5 } }) .then(function(result){ var product=result.data; }) </script>
十七题
js事件机制?
捕获 目标触发 冒泡
十八题
浏览器的缓存问题?
当浏览器请求一个网站的时候,会加载各种各样的资源,比如HTML
文档、图片、CSS
和JS
等文件。对于一些不经常变的内容,浏览器会将他们保存在本地的文件中,下次访问相同网站的时候,直接加载这些资源,加速访问。
这些被浏览器保存的文件就被称为缓存。(不是指Cookie
或者Localstorage
)。
解决方法 :
ctrl + f5:强制刷新
遇到图片缓存问题,可以在请求的url路径后加 ?new Date()
十八题
js如何区分数组和对象?
<script> console.log( {}.constructor ) // Object console.log( [].constructor ) // Array console.log( {} instanceof Array ) //false console.log( [] instanceof Array ) // true console.log( Array.isArray({}) ) //false console.log( Array.isArray([]) ) // true
console.log( toString.call( {} ) ) //[object Object]
console.log( toString.call( [] ) ) //[object Array]
</script>
十九题
<script> var User = { count : 1, getCount : function () { return this.count } } console.log(User.getCount()) // 1 var func = User.getCount; console.log( func() ) // undefined </script>
二十题
for ( var i = 1; i <= 3; i++){ setTimeout (function () { console.log(i) // 三个 4 },0) }
二十一题
<script> var name = 'jack'; function change () { alert(name); //undefinded var name = 'lily' alert(name) // lily } change(); </script>
二十二题
javascrip是如何继承的?
原型链继承方式 或者 借用构造函数(使用call/apply)
- 200 - 请求成功
- 301 - 资源(网页等)被永久转移到其它URL
- 404 - 请求的资源(网页等)不存在
- 500 - 内部服务器错误
二十三题
<script> setTimeout(() => { console.log('setTimeout') }, 0); let p1 = new Promise( (resolve)=>{ console.log('promise1') resolve('promise2') } ) p1.then( (res)=>{ console.log(res) }) console.log(1) // 打印结果是? // promise1 1 promise2 setTimeout </script>
二十四题
vue中二级联动怎么做?
使用嵌套路由
router-view vue-router的配置,使用children[ ]
二十五题
// Object.keys(arr) 中放入数组,会以字符串的形式,返回所有数组的下标 输出的是[]格式 var arr = ['z','h','y'] console.log( Object.keys(arr) ) //["0", "1", "2"] // Object.keys(arr) 中放入对象,会以字符串的形式,返回所有对象中的属性名 输出的是[]格式 var obj = { name:'zh', age:18, money:9999999999 } console.log( Object.keys(obj) ) //["name", "age", "money"]
// 输出对象中值大于2的key的数组 var data = {a:1,b:2,c:3,d:4} // ['a','b','c','d'] var result = Object.keys(data).filter(function(k){ return k!='a'&&k!='b' }) console.log(result) // 期待输出 ['c' , 'd']
二十六题
<script> (function(){ var a=b=5; // b=5; })(); // var a = b; console.log(b) // 5 console.log(a) // a is not defined </script>
二十七题
http与https,运营商注入问题
HTTP(超文本传输协议)被用于在Web浏览器和网站服务器之间,以明文方式传递信息,不提供任何方式的数据加密,因此使用HTTP协议传输隐私信息(如:银行卡号、密码等支付信息)非常不安全。 数据可以被劫持注入广告
HTTPS协议="SSL+HTTP协议"构建的可进行加密传输、身份认证的网络协议,是HTTP的安全版。
二十八题
浏览器渲染机制,渲染引擎以及js引擎
V8引擎是? js引擎 负责执行js代码
渲染引擎? 负责执行 html css 等代码
二十九题
var foo = 1; function bar () { if(!foo){ //变量提升 !undefined var foo = 10; } console.log(foo) // 10 } bar();
三十题
<script> var n = 0; function a () { var n = 10; function b () { n++; console.log(n); } b(); // 11 return b; } var c = a(); c(); // 12 console.log(n) // 0 // 输出 : 11 12 0 </script>
三十一
<script> var a = 10,b=11,c=12; function fn (a) { a = 1; var b = 2; c = 3; } fn(10); // 传入实参 10 ,就相当于在函数中var a = 10 console.log(a);//10 console.log(b);//11 console.log(c);//3 </script>
三十二题
<script> // in: 检测某一个属性是否属于这个对象(不管是私有属性还是公有属性)
if(!('a' in window)){// window中 有没有 a var a = 1; } console.log(a)//undefined // 解题思路: 因为变量提升,var a 提升到最前边,全局中有了a,所以 'a' in window 是true </script>
三十三题
var a = 9; function fn () { a = 0; return function (b) { return b+a++; } } var f = fn(); console.log( f(5) ) // 5 console.log( fn()(5) ) // 5 console.log( f(5) ) // 6 console.log( a ) // 2
三十三题
var arry = [1,2,3,4]; // arry = aaafff000 ([1,2,3,4]) 地址 function fn (arry) {//aaafff000 arry = aaafff000 arry[0]=0; // [0,2,3,4] arry=[0]; // [0] 创建了一个新地址 bbbfff000, arry=bbbfff000 引用值:[0] arry[0]=100; // bbbfff000[0]=100 , 引用值 :[100] return arry // [100] } var res = fn(arry) //[100] console.log(arry) // 输出 [0,2,3,4] console.log(res) // 输出 [100]
三十三题
function fn (i) { return function (n) { console.log( n + (i++) ); } } var f = fn(10); f(20); //30 fn(20)(40); // 60 fn(30)(50); // 80 f(30) // 41
三十四题
<script> var i = 10; function fn () { return function (n) { console.log( n + (++i) ); } } var f = fn(); f(20); //31 fn()(20); //32 fn()(30); //43 f(30) //44 </script>
<!-- 解题思路: 匿名函数自调中的this 指向 window 方法调用中的this指向.前的对象 --> <script> var num = 10; var obj = { num:20 } obj.fn = (function (num) { this.num = num * 3 num++; return function (n) { this.num += n num++ console.log(num) } })(obj.num) var fn = obj.fn fn(5);//22 obj.fn(10);//23 console.log(num,obj.num) //65 30 </script>
<!-- 解题思路: 匿名函数自调中的this 指向 window 方法调用中的this指向.前的对象 --> <script> var num = 10; var obj = { num:20 } obj.fn = (function (num) { num = this.num + 10; this.num = num + 10; return function () { this.num += num } })(num) var fn = obj.fn fn(); obj.fn(); console.log(num,obj.num) //50 40 </script>
三十五题
<!-- 解题思路:元素绑定事件,方法中的this是当前操作的元素 方法名前面是否有点,有点,点前面是谁this就是谁,没有.this是window(严格模式下是undefined) 构造函数执行,方法体中的this指向向new出来的对象 --> <script> var fullName = 'language'; var obj = { fullName : 'javascript', prop:{ getFullName:function (){ return this.fullName } } } console.log(obj.prop.getFullName()); //undefined var test = obj.prop.getFullName; console.log( test() ) //language
三十六题
<!-- 解题思路:new做的四件事 创建一个新的对象 调用函数 改变this指向 返回一个新的对象 查找规则:先从自己身上找,如果找不到再去原型上找 --> <script> function fun () { this.a=0; this.b=function () { alert(this.a) } } fun.prototype = { b:function (){ this.a = 20 alert(this.a) }, c:function (){ this.a=30 alert(this.a) } } var my_fun = new fun();//新对象 my_fun.b();// alert 0 my_fun.c();// alert 30 </script>
三十七题
<script> function Fn () { var n = 10; this.m = 20; this.aa = function () { console.log(this.m) } } Fn.prototype.bb = function () { console.log( this.n ) } var f1 = new Fn; Fn.prototype = { aa:function () { console.log(this.m+10) } } var f2 = new Fn; console.log( f1.constructor ) // Fn console.log( f2.constructor ) // Object f1.bb() // undefined f1.aa() // 20 // f2.bb() //报错 f2.aa() //20 f2.__proto__.aa() //NaN </script>
三十八题
//依次遍历数组中的每一项,让每一项的值作为对象的属性名和属性值(属性值存什么都可以),每一次存储之前验证当前对象中是否已经存在这个属性了(in/hasOwnProperty/属性值不是undefined),
如果有这个属性了,说明当前项在数组中已经存在了,我们把当前项在原有数组中移除,如果不存在,存储到对象中即可 var ary = [1,1,1,1,1,2] function unique (ary) { var obj = {}; for ( var i = 0; i < ary.length; i++){ /* 优化:不使用splice删除(删除当前项,后面索引移动位置,如果后边有很多项,到性能消耗大) 解决:把最后一项替换当前项,删除最后一项即可(会改变原有数组的排序) */ var item = ary[i] if( obj.hasOwnProperty(item) ){//如果元素已经存在 ary[i] = ary[ary.length-1];// 当前项 = 最后一个元素 ary.pop() i-- continue; } obj[item]=item; } obj = null ; //优化:obj没有之后手动释放一下,节约内存 return ary } console.log( unique(ary) ) //[1, 2]
终极优化版
<script> /* 用对象键值对的方式来减少双for循环带来的循环次数过多,性能消耗 对象键值对里解决数组塌陷问题 删除数组元素,导致数组索引位移问题 手动释放堆内存 把方法扩展到内置类的原型上 */ var ary = [1,1,2,2,3,4,5] Array.prototype.my_unique = function my_unique () { var obj = {}; for ( var i = 0; i<this.length; i++) {//this 指向方法.前的对象ary var item = this[i] obj.hasOwnProperty(item)?(this[i]=this[this.length-1],this.pop(),i--):obj[item]=item } //判断对象obj中是否有item元素,如果有 让当前元素等于数组最后一个元素,删除最后一个元素 // 如果没有 将这个元素添加到对象中 this.sort((a,b)=>{return a-b})// 数组去重后 按升序排列 obj = null; } ary.my_unique() console.log(ary) // [1, 2, 3, 4, 5] </script>
三十九题
三十九题
(function(x){ delete x alert(x) })(5+1) // 输出结果: 是 弹出 6
四十二题目
/* 实现一个$attr(name,vlaue) 属性为 name 值为value的元素集合 */
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div name='AA' class="box clearfix"></div>
<div class="content box"></div>
<div name='BB'></div>
<div id="AA"></div>
<div class="box"></div>
<div name='BB'></div>
<div name='AA' class="box clearfix"></div>
<script>
let ary = $attr('name','box'); // 获取页面中所有name为box的元素
// 思路:获得页面中所有的标签,循环得到每一个标签
function $attr(property,vlaue) {
// 获取当前页面中所有的标签
let elements = document.getElementsByTagName('*');
elements = Array.from(elements)// 将elements变为数组
console.log(elements instanceof Array)
arr = [];
[].forEach.call(elements,function(item){
// 存储的是当前的元素property对应的属性值
let itemValue = item.getAttribute(property)
if(property==='class'){
// 样式类属性名要特殊的处理
new RegExp("\b"+vlaue+"\b").test(itemValue)? arr.push(item):null;
return
}
if(itemValue === vlaue){
arr.push(item)
}
})
return arr
}
console.log($attr('name','AA') )
</script>
</body>
</html>
四十三题
<script>
let str = '你好,word哈哈哈aaa不错'
reg = /[a-z]+/
str=str.replace(reg,(item)=>{
return ' ' + item + ' '
}).trim()
console.log(str); // 你好, word 哈哈哈aaa不错
</script>
四十四题目
数组扁平化(可以通过es6的flat 或者 数组.toString()转为对象,再split(',')转回数组)
<script>
// 编写一个程序,将数组扁平化,并去除其中重复部分数据,最终得到一个升序且不重复的数组
let arr = [[1,2,2],[3,4,5,5],[6,7,8,9,[11,12,[12,13,14]]],10]
// 使用es6中提供的Array.prototype.flat 处理 将数组扁平化
arr=arr.flat(Infinity)
var result = new Set(arr)
result = [...result].sort((a,b)=>{return a-b})
console.log(result);
</script>
<script>
// 编写一个程序,将数组扁平化,并去除其中重复部分数据,最终得到一个升序且不重复的数组 let arr = [[1,2,2],[3,4,5,5],[6,7,8,9,[11,12,[12,13,14]]],10] // 使用es6中提供的Array.prototype.flat 处理 将数组扁平化 arr=arr.toString().split(',').map((item)=>{ return Number(item) }).sort((a,b)=>{return a-b}) console.log(arr) </script>