1. 作用域的传递
<script type="text/javascript">
//作用域
var num1 = 55;
var num2 = 66;
function f1(num,num1){
//var num = 55;
//var num1 = 66;
num = 100;//100
num1 = 100;//100
num2 = 100;//100
console.log(num);//100
console.log(num1);//100
console.log(num2);//100
}
// 55 66
f1(num1,num2);
//打印结果
console.log(num1)//55
console.log(num2)//100
console.log(num);//报错
</script>
2. 值类型和引用类型的传递
<script type="text/javascript">
function Person(name,age,salary){
this.name = name;
this.age = age;
this.salary = salary;
}
function f1(person){
person.name = "ls";
person = new Person("aa",18,10);
}
var p =new Person("zs",18,1000);
console.log(p.name);//打印输出zs
f1(p);
console.log(p.name);//打印输出ls
</script>
3. 封装函数进行字符串驼峰命名的转换
<script type="text/javascript">
//已知有字符串foo=‘get-element-by-id’,写一个function将其转化成驼峰表示法“getElementById”
var foo = 'get-element-by-id';
//根据某个字符进行切割
var arr = foo.split("-");
//打印数组
console.log(arr);//["get","element","by","id"]
//获取每个元素中的第一个字符并转换成大写
console.log(arr[1].charAt(0).toUpperCase()+arr[1].substr(1,arr[1].length-1));
for(let i = 0;i<arr.length;i++){
arr[i] = arr[i].charAt(0).toUpperCase()+arr[i].substr(1,arr[i].length-1);
}
console.log(arr.join(""));//getElementById
//自定义函数
function toString(){
var foo = 'get-element-by-id';
//根据某个字符进行切割
var arr = foo.split("-");
//打印数组
console.log(arr);//["get","element","by","id"]
//获取每个元素中的第一个字符并转换成大写
console.log(arr[1].charAt(0).toUpperCase()+arr[1].substr(1,arr[1].length-1));
for(let i = 0;i<arr.length;i++){
arr[i] = arr[i].charAt(0).toUpperCase()+arr[i].substr(1,arr[i].length-1);
}
//根据某个字符将数组转换成字符串
return arr.join('');
}
console.log(toString('get-element-by-id'));//getElementById
</script>
4. 冒泡排序
<script type="text/javascript">
var arr = [5,4,3,2,1];
//轮数
for(let i=0;i<arr.length-1;i++){
//次数
for(let j=0;j<arr.length-1-i;j++){
//判断前一个大于后一个数时进行交换
if(arr[j]>arr[j+1]){
//借助第三方变量交换两个变量的值
var temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
console.log(arr);//打印输出[1,2,3,4,5]
</script>
5.反转数组
<script type="text/javascript">
var arr = [1,2,3,4,5,6,7,8];// 测试用例
for(let i=0;i<arr.length/2;i++){
//arr[0] arr[arr.length-1-0]
//arr[1] arr[arr.length-1-1]
//arr[2] arr[arr.length-1-2]
//arr[3] arr[arr.length-1-3]
//借助第三方变量进行变量交换
var temp = arr[i];
arr[i] = arr[arr.length-1-i];
arr[arr.length-1-i] = temp;
}
console.log(arr);//[8,7,6,5,4,3,2,1]
</script>
6.去掉数组中重复性的数据
<script type="text/javascript">
/*
1.创建一个新数组,把原数组中的第一个元素插入到新数组中
2.遍历原数组中的每一个元素分别和新数组中的每一个元素进行比较
*/
//原数组
var arr = [0,11,20,5,20,8,0,2,4,0,8];
//新数组
var t = [8,11,20,5];
t[0] = arr[0];
//arr中的每个元素
for(let i=0;i<arr.length;i++){
//t中的每个元素
for(let k=0;k<t.length;k++){
//当原数组中的值和新数组中的值相同时,就没有必要进行比较,跳出内循环
if(t[k]==arr[i]){
break;
}
//拿原数组中的某个元素比较到新数组中的最后一个元素还没有重复
if(k == t.length-1){
//将数据插入新数组
t.push(arr[i]);
}
}
}
console.log(t);
</script>
7.1px物理像素实现
方案一:
<style>
*{
margin:0;
padding:0;
}
#box{
width:0.5rem;
height:0.5rem;
border-bottom:1px solid #000;
}
</style>
<!--像素比 = 物理像素/css像素-->
<script type="text/javascript">
window.onload = function(){
//像素比
var dpr = window.devicePixelRatio;
//缩放比例
var scale = 1/dpr;
//获取meta标签
var metaNode = document.querySelector('meta[name="viewport"]');
metaNode.setAttribute('content','width=device-width,initial-scale="+scale+",user-scalable=no')
//页面中的元素宽度,高度,比例反向乘回来
var htmlNode = document.querySelector("html");
htmlNode.style.fontSize = width * dpr + "px";
}
</script>
方案二:
#box{
width:200px;
height:200px;
position:relative;
}
#box:before{
content:'';
position:absolute;
left:0;
bottom:0;
widht:100%;
height:1px;
background:#000;
}
@media screen and (-webkit-min-device-pixel-ratio:2){
#box:before{
transform:scaleY(0.5);
}
}
@media screen and (-webkit-min-device-pixel-ratio:3){
#box:before{
transform:scaleY(0.333333);
}
}
8. 实现元素水平垂直居中
html代码:
<div id="wrap">
<div class="box"></div>
</div>
CSS代码:
*{
margin:0;
padding:0;
}
#warp{
width:500px;
height:500px;
background:grey;
position:relative;
----使用flex实现水平垂直居中(新版本)---------
display:flex;
justify-content:center;
align-item:center;
----使用flex实现水平垂直居中(老版本)---------
display:-webkit-box;
-webkit-box-pack:center;
-webkie-box-align:center;
}
#wrap .box{
width:200px;
height:200px;
background:pink;
方案一:
position:absolute;
top:0;
left:0;
right:0;
buttom:0;
margin:auto;
------------------
方案二:
position:absolute;
top:50%;
left:50%;
margin-left:-100px;
margin-top:-100px;
-----------------------
方案三:
position:absolute;
top:50%;
left:50%;
transform:translate(-50%,-50%);
}
9. 纯CSS实现一个三角形
*{
margin:0;
padding:0;
}
#box{
width:0px;
height:0px;
border:100px solid;
---四条边,三条边是透明色,只有显示的那条边是有颜色---
border-top-color:red;
border-right-color:transparent;//透明色
border-bottom-color:transparent;//透明色
border-left-color:transparent;//透明色
}
10.如何实现移动端rem适配
HTML代码:
<body>
<div id="box"></div>
</body>
CSS代码:
*{
margin:0;
padding:0;
}
#box{
width:1rem;
height:1rem;
background:red;
}
/**
html根元素字体大小设置屏幕区域的宽度
*/
JavaScript代码:
window.onload = function (){
//获取屏幕区域的宽度
var width = document.documentElement.clientWidth;
//获取html
var htmlNode = document.querySelector("html");
//设置字体大小
htmlNode.style.fontSize = width + "px";
}
11.求背景图片左边到#box盒子左边框外侧的距离
CSS代码:
*{
margin:0;
padding:0;
}
#box{
width:100px;
height:200px;
background:pink;
padding:100px;
border:80px solid blue;
background-image:url("iamge/1.png");
background-repeat:no-repeat;
background-origin:content-box;/*背景图片起始源的位置*/
background-position:-50px 0;
}
/*130px*/
12.js综合面试题
function Foo(){
getName = function(){
alert(1);
return this;
}
}
Foo.getName = function(){
alert(2);
};
Foo.prototype.getName = function(){alert(3);};
var getName = function(){alert(4);};
function getName(){alert(5);}
//请写出下列的输出结果
Foo.getName();//输出2
getName();//输出4
Foo().getName();//(window.Foo()).getName()--->window.getName() 输出1
getName();//输出1
new Foo.getName();//new (Foo.getName)()--> new(function(){alert(2);})() 输出2
new Foo().getName();//(new Foo()).getName() --> foo.getName() 输出3
new new Foo().getName();//new ((new Foo()).getName)()--> new (foo.getName)()-->new (function(){alert(3);}) 输出3
13.函数节流和防抖
//面试题,什么是函数节流? 什么是函数防抖
/**
函数节流,一个函数执行一次后,只有大于设定的执行周期后才会执行第二次。
- 有个需要频繁触发函数,出于优化性能角度,在规定时间内,只让函数触发的第一次生效,后面不生效
*/
/**
*节流函数
*@param fn 要被节流的函数
*@param delay 规定的时间
*/
节流函数
CSS代码:
html,body{
height:500%;
}
JavaScript代码:
function throttle(fn,delay){
//记录上一次函数触发的时间
var lastTime =0;
return function(){
//记录当前函数触发的时间
var nowTime = Date.now();
if(nowTime - lastTIme > delay){
//修正this指向问题
fn().call(this);
//同步时间
lastTime = nowTime;
}
}
}
document.onscroll = throttle(function(){
console.log("scroll事件被触发了" + Date.now(),200);
})
防抖函数
/**
防抖函数:一个需要频繁触发的函数,在规定的时间内,只让最后一次生效,前面的不生效
*/
function debounce(fn,delay){
//记录上一次的延时器
var timer = null;
return function(){
//清除上一次延时器
clearTimeout(timer);
//重新设置新的延时器
timer = setTimeout(function(){
fn.apply(this);
},delay);
}}
document.getElementById("btn").onclick = debounce(function(){console.log("点击事件被触发了"+Date.now());},1000)
html代码:
<body>
<buttom id="btn">
按钮
</buttom>
</body>
14.什么是跨域?解决跨域的办法有哪些?
- 同源策略
- 是浏览器安全策略
- 协议名,域名,端口号必须完全一致 - 跨域
违背同源策略就会产生跨域 - 解决跨域
jsonp cors 服务器代理…
JavaScript代码:
创建script标签
var script = document.createElement("script");
//设置回调函数
function getData(data){
//数据请求回来会被触发的函数
console.log(data);
}
//设置script的src属性,设置请求地址
script.src = "http://localhost:3000?callback=getData"
//让script生效
document.body.appendChild(script);
15.nodejs的事件轮询机制
setTimeout(function(){
console.log("setTimeout()");
},0)
setImmediate(function(){
console.log("setImmediate()");
})
process.nextTick(function(){
console.log("process.nextTick()");
})
//执行结果跟函数的位置没有关系
/*
process.nextTick()
setTimeout()
setImmediate()
nodejs的事件轮询机制:借助libuv库实现的
概括事件轮询机制,分为6个阶段:
1.timers 定时器阶段
计时和执行到点的定时器回调函数
2.pending callbacks
某些系统操作(例如TCP错误类型)的回调函数
3.idle,prepare
准备工作
4.poll轮询阶段(轮询队列)
如果轮询队列不为空,依次同步取出轮询队列中第一个回调函数执行,直到轮询队列为空或者达到系统的最大的限制
如果轮询队列为空
如果之前设置过setImmediate函数
直接进入下一个check函数
如果之前没有设置过setImmediate函数
在当前poll阶段等待
直到轮询队列添加回调函数,就去第一个情况执行
如果定时器到点了,也会去下一个阶段
5.check 查阶段
执行setImmediate设置的回调函数
6.close callbacks 关闭阶段
执行close 事件回调函数
process.nextTick能在任意阶段优先执行
*/
16.从一个URL地址都最终页面渲染完成,发生了什么?
- DNS解析:将域名地址解析成IP地址
- 浏览器DNS缓存
- 系统DNS缓存
- 路由器DNS缓存
- 网络运营商DNS缓存
- 递归搜索 blog.baidu.com
- .com域名下查找DNS解析
- .baidu域名下查找DNS解析
- blog域名下查找DNS解析
- 出错了 - TCP连接:TCP三次握手
- 第一次握手,由浏览器发起,告诉服务器我要发送请求了
- 第二次握手,由服务器发起,告诉浏览器我准备接受了,你赶紧发送吧
- 第三次握手,由浏览器发送,告诉服务器,我马上就发了,准备接受吧 - 发送请求
- 请求报文:HTTP协议的通信内容 - 接受响应
- 响应报文 - 渲染页面
- 遇见HTML标记,浏览器调用HTML解析器解析成Token并构建成dom树
- 遇见style/link标记,浏览器调用CSS解析器,处理CSS标记并构建CSSdom树
- 遇到script标记,调用JavaScript解析器,处理script代码(绑定事件,修改dom树/cssom树)
- 将dom树和CSSOM树合并成一个渲染树
- 根据渲染树来计算布局,计算每个节点的几何信息(布局)
- 将各个节点颜色绘制到屏幕上(渲染)
注意:
这个五个步骤不一定按照顺序执行,如果dom树或CSSom树被修改了,可能会执行多次布局和渲染
往往实际页面中,这些步骤都会执行多次的。
- 断开连接:TCP四次挥手
第一次挥手:由浏览器发起的,发送给服务器,我东西发送完了(请求报文),你准备关闭吧
第二次挥手:由服务器发起的,告诉浏览器,我东西接受完了(请求报文),我准备关闭了,你也准备吧
第三次挥手:由服务器发起,告诉浏览器,我东西发送完了(响应报文),你准备关闭吧
第四次挥手:由浏览器发起,告诉服务器,我东西接受完了,我准备关闭了(响应报文),你也准备吧
17.闭包
什么是闭包?
- 密闭的容器,类似于set,map容器,存储数据的
- 闭包是一个对象,存放数据的格式:key:value
形成的条件:
- 函数嵌套
- 内部函数引用外部函数的局部变量
闭包的优点:
延长外部函数局部变量的生命周期
闭包的缺点:
容易造成内存泄漏
注意点:
1.合理的使用闭包
2.用完闭包要及时清除(销毁)
JavaScript代码:
function fun(){
var count = 1;
function fun2(){
console.log(count);
}
fun2();
}
fun();
闭包的应用场景
function fun(){
var count = 1;
return function(){
count++;
console.log(count);
}
}
var fun2 = fun();
fun2();//2
fun2();//3
说说它们的输出情况
function fun(n,o){
console.log(o);
return {
fun:function(m){
return fun(m,n);
}
}
}
var a = fun(0);
a.fun(1)
a.fun(2)
a.fun(3)//undefined,0,0,0
var b = fun(0).fun(1).fun(2).fun(3)//undefined,0,1,2
var c = fun(0).fun(1);
c.fun(2);
c.fun(3);//undefined,0,1,1
18.变量提升 && 执行上下文
变量提升 预处理
/**
js引擎在代码正式执行之前会做一个预处理的工作
1.收集变量
2.收集函数
依据:
var 将var后边的变量定义但是不赋值 var username = undefined;
function(){}提前定义该函数
*/
console.log(username);//报错 答案:undefined
var username = "kobe";
console.log(username);//kobe
fun(); //报错 答案:正确执行函数
function fun(){
console.log("fun()");
}
执行上下文 执行上下文对象
执行上下文(execute context)EC
理解:代码执行的环境
时机:代码正式执行之前会进入到执行环境
工作:
1.创建变量对象
1)变量
2)函数及函数的参数
3)全局:window
4)局部:抽象的但是确实存在
2.确认this的指向
1)全局:this ---->window
2)局部:this ----->调用其的对象
3.创建作用域链
父级作用域链 + 当前的变量对象
4.扩展
ECObj = {
变量对象:{变量,函数,函数的形参}
scopeChain:父级作用域链 + 当前的变量对象,
this:{window || 调用其的对象 }
}
19.宏任务和微任务
什么是宏任务?
分类:setTimeout setInterval requrestAnimationFrame
1.宏任务所处的队列就是宏任务队列
2.第一个宏任务队列中只有一个任务:执行主线程的js代码
3.宏任务队列可以有多个
什么是微任务?
分类: new Promise().then(回调) process.nextTick
1.微任务所处的队列就是微任务队列
2.只有一个微任务队列
3.在上一个宏任务队列执行完毕后如果有微任务队列就会执行微任务队列中的所有任务
4.当宏任务队列中的任务全部执行完以后会查看是否有微任务队列,如果有,先执行微任务队列中的所有任务,如果没有就查看是否有宏任务队列
JavaScript代码:
console.log("---------start----------------");
setTimeout(()=>{
console.log("setTimeout");
},0)
new Promise((resolve,reject)=>{
for(var i = 0;i<5;i++){
console.log(i);
}
resolve();//修改promise实例对象的状态为成功的状态
}).then(()=>{
console.log("promise实例成功回调执行");
})
console.log("------------end-------------------");
20.Vue和React的区别
相同点:
- 都有组件化开发和Virtual DOM
- 都支持props进行父子组件间数据通信
- 都支持数据驱动视图,不直接操作真实DOM,更新状态数据界面就自动更新
- 都支持服务器端渲染
- 都有支持native的方案,React的React Native,Vue的Weex
不同点:
- 数据绑定:Vue实现了数据的双向绑定,react数据流动是单向的
- 组件写法不一样。React推荐的做法是JSX,也就是把HTML和CSS全都写进JavaScript,即“all in js”,Vue推荐的做法是webpack + vue + loader的单文件组件格式,即html,css,js写在同一个文件
- state对象在react应用中不可变的,需要使用setState方法更新状态;在Vue中,state对象不是必须的,数据由data属性在Vue对象中管理
- virtual DOM不一样,Vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树,而对于React而言,每当应用的状态被改变时,全部组件都会重新渲染,所以react中会需要shouldComponentUpdate这个生命周期函数方法来进行控制
- React严格上只针对MVC的View层,Vue则是MVVM模式
21.Redux管理状态的机制
- redux是一个独立专门用于做状态管理的JS库,不是react插件库
- 它可以用在React,angular,Vue等项目中,但基本与React配合使用
- 作用:集中式管理React应用中多个组件共享的状态和从后台获取的数据
Redux的工作原理
Redux使用扩展
- 使用React-redux简化redux的编码
- 使用Redux-thunk实现redux的异步编程
- 使用Redux DevTools实现chrome中Redux的调试
22.说说Vue组件间通信方式
通信种类
- 父组件向子组件通信
- 子组件向父组件通信
- 隔代组件间通信
- 兄弟组件间通信
实现通信方式
- props
- Vue自定义事件
- 消息订阅与发布
- Vuex
- slot
方式1:props
- 通过一般属性实现父向子通信
- 通过函数属性实现子向父通信
- 缺点:隔代组件和兄弟组件间通信比较麻烦
方式2:Vue自定义事件
Vue内置实现,可以代替函数类型的props
a. 绑定监听:<MyComp @eventName = “callback”>
b.触发(分发)事件:this.$emit(“eventName”,data)缺点:只适合于子向父通信
方式3:消息订阅与发布
需要引入消息订阅与发布的实现库,如:pubsu-js
a.订阅消息:PubSub.subscribe(“msg”,(msg,data)=>{})
b.发布消息:PubSub.publish(“msg”,data)优点:此方式可实现任意关系组件间通信
方式4:Vuex
- 是什么:Vuex是Vue官方提供的集中式管理Vue多组件共享状态数据的Vue插件
- 优点:对组件间关系没有限制,且相比于pubsub库管理更集中,更方便
方式5:slot
- 是什么:专门用来实现父向子传递带数据的标签
a.子组件
b.父组件 - 注意:通信的标签模板是在父组件中解析好后再传递给子组件的
23.Vuex管理状态的机制
- 对Vuex基本理解
1)是什么:Vuex是一个专门为Vue.js应用程序开发的状态管理的Vue插件
2)作用:集中式管理Vue多个组件共享的状态和从后台获取的数据 - Vuex的工作原理
24.说说Vue的MVVM实现原理
- 理解
1)Vue作为MVVM模式的实现库的2种技术
a.模板解析
b.数据绑定
2)模板解析:实现初始化显示
a.解析大括号表达式
b.解析指令
3)数据绑定:实现更新显示
a.通过数据劫持 - 原理结构图
如果您正好遇到这个问题,看了我的文章之后您的问题解决了,那就点赞留言关注一下撒!!!
欢迎三连!!!😀😀😀
CSDN:听说你很会玩
Github:zhongzhimao
杰灵软件:杰灵软件官网
微信公众号:杰灵软件