记录前端的面试日常(持续更新)
写在前面的话
又到了跳槽的季节,现在也该总结一下自己在前端积累这么多年的一点珍藏的货色了,注意了我主要总结是尽量用自己能表达的想法去说,所有可能没别人总结的那么客观,还有尽量用简短的话简单的思路去表达应该有的意思,方便记忆理解,还有这篇博文我会持续更新的
什么叫优雅降级和渐进增强(这个其实很多的,但是我是不可能去背的,所有尽量用少的话,总结清楚)
.transition{ -webkit-transition: all .5s; -moz-transition: all .5s; -o-transition: all .5s; transition: all .5s; }//渐进增强 .transition{ transition: all .5s; -o-transition: all .5s; -moz-transition: all .5s; -webkit-transition: all .5s; }//优雅降级
优雅降级:一开始就构建完整的功能,然后再针对低版本浏览器进行兼容
渐进增强:针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果.交互等改进和追加功能达到最好的用户体验
jQuery的实现原理
(functon(window,undefined){})(window)
jQuery利用JS函数作用域的特性,采用立即调用表达式包裹了自身,解决命名空间和变量污染问题
window.jQuery=window.$=jQuery
在闭包当中将jQuery和$()绑定到window上,从而jQuery和$暴露为全局变量
jQuery.fn的init方法返回的this就是jQuery对象
核心是对DOM
操作进行的封装,以避免单独实现不同浏览器的兼容代码
通过代理对象,给不同的对象监听事件,进行管理
jQuery 的属性拷贝(extend)的实现原理是什么,如何实现深拷贝?
浅拷贝(只复制一份原始对象的引用)
- var newObject=$.extend({},oldObject)
深拷贝(对原始对象实行所引用的对象进行递归拷贝)
JSON对象parse方法可以将JSON字符串反序列化成js对象,stringify方法可以将js对象序列化成json字符串,这两种方法产生一个便捷的深克隆
- var newObject=$.extend(true,{},oldObject)
深浅拷贝的区别
深拷贝之后,改变其中一个值,不会影响另外一个值,浅拷贝则会影响
浅拷贝只是拷贝了指向对象的指针
而深拷贝则是完全拷贝整个值,创建了一个新的和原对象一样的对象
清除浮动
第一种
overflow:hidden
第二种
.clearfix:after{ content:".", diplay:block; hieght:0; clear:both; visibility:hidden; }
最快速的数组求最大值
var arr=[1,2,12,5,6]; Math.max(...arr);//es6 math.max.apply(null,arr)//es5 apply //for循环 let max=arr[0]; for(let i=0;i<arr.length-1;i++){ max=arr[i]<arr[i+1]?arr[i+1]:arr[i] } //数组sort() arr.sort((num1,num2)=>{return num1-num2<0})//回忆a-b升序b-a降序,同理喔 arr[0] //数组reduce //这个还是需要科普一下 //aray的reduce()把一个函数作用在整个Array的[x1,x2,x3,x4...]上,这个必须接受两个 //参数,reduce()把结果继续和序列的下一个元素做累计计算,怎么感觉有点像map //感觉没有解释清楚,下面给个地址 arr.reduce((num1,num2){return num1>num2?num1:num2})
数组去重
[... new Set([2,"23","2","5",12,5,6,12])]
最快速的方式
- 最简单的方法
function arr1(){ var n=[]; for(var i=0;i<arr.length;i++){ if(n.indexOf(arr[i])==-1){ n.push(arr[i]) } } return n; }
cookie . sessionStorage . localStorage的区别资料
cookie是网站为了标识用户身份而存储在用户本地终端上的数据
cookie数据使用在同源的http请求中携带,会在浏览器和服务器来回传递
webStorage目的:克服cookie带来的一些限制,当数据需要被严格控制在客户端是,不需要持续的将数据发回服务器
webstorage提供两种API:localstorage(本地存储)和sessionStorage(会话存储)
生命周期:
localStorage(本地存储)
- 永久的,关闭网页也不会消失,除非主动删除数据
sessionStorage(会话存储)
- 数据在当前浏览器窗口关闭后自动删除
cookie 设置的cookie过期时间之前一直有效,即使浏览器关闭
locaStorage(本地存储)和sessionStorage(会话存储)不会自动把数据发给服务器,仅仅本地保存
存储大小:
- cookie -->4k
- sessionStorage和localStorage -->5m或更大
javascript有几种类型的值
栈:原始数据类型(undefined,null,Boolean,number,string)
堆:引用数据类型(对象,数组,函数)
区别:存储位置不同
原始类型数据直接存储在栈的简单数据段
- 占据空间小,大小固定,属于被平凡使用数据,所以放在栈中存储
引用数据类型存储在堆中的对象
- 占据空间大,大小不固定,如果存储在栈中,将会影响程序运行的性能
- 引用数据类型在栈中存储了指针,该指针指向该实体的起始地址
- 当解释器寻找引用值时,会首先检索在栈中的地址,取得地址后从堆中获取实体
javascript如何实现继承
原型prototype机制或apply和call方法去实现较简单,建议使用构造函数与原型混合方式。
function Parent(){
this.name = 'wang';
}
function Child(){
this.age = 28;
}
Child.prototype = new Parent();//继承了Parent,通过原型
var demo = new Child();
alert(demo.age);
alert(demo.name);//得到被继承的属性
什么是doctype
DTD就是告诉浏览器我是什么文档类型,用这个来判断我用什么来解析它渲染它
doctype就是通知浏览器哪个DTD和文档类型
<!doctypehtml>
--->HTML5
HTML4.0有两个模式:严格模式和宽松模式
内核的理解
分为两个部分:渲染引擎和js引擎
渲染引擎:负责取得网页的内容(html,css)
js引擎:解析和执行javascript来实现网页的动态效果,但是后来js引擎越来越独立了(V8引擎)
有一个长度100的数组,算前10项的和
var a=[1,2,34,4,5,6,76,7,1,2,3,4,5,6,7]
sun=null;
sun=a.slice(0,10).reduce(function(pre,current){
return pre+current;
})
console.log(sun);//reduce可以看前面最大值
javascript优化
松耦合:当修改一个组件而不需要改其他组件时,就做到松耦合
将js从css中抽出,不要使用css表达式
将css从js中抽出:通过js修改css样式时,使用className或classList
将js从html抽离:从js外置文件
将HTML从js中抽离:不要使用innerHTML使用字符串模板
HTML.css.JS三者的关系应当时相互独立分离的,如果产生交集,出现紧耦合代码,就违反了代码可维护性原则
全局变量
零全局变量(function(){})(window)
单全局变量(jQuery)和命名空间
模块
事件处理
隔离应用逻辑(将应用逻辑和事件处理的代码拆分开)
var MyApplication = {
handleClick: function(event){
this.showPopup(event);
},
showPopup: function(event){
var popup = document.getElementById('popup');
popup.style.left = event.clientX + 'px';
popup.style.top = event.clientY + 'px';
popup.className = 'reveal';
}
};
addListener(element,'click',function(event){
MyApplication.handleClick(event);
});
不要分发事件对象
让事件处理程序使用event对象来处理事件,然后拿到所有需要的数据传到应用逻辑
//改进的做法
var MyApplication = {
handleClick: function(event){
this.showPopup(event.clientX,event.clientY);
},
showPopup: function(x,y){
var popup = document.getElementById('popup');
popup.style.left = x + 'px';
popup.style.top = y + 'px';
popup.className = 'reveal';
}
};
addListener(element,'click',function(event){
MyApplication.handleClick(event);
});
记得在事件处理程序应当在进入应用逻辑之前针对event对象执行任何必要的操作,包括阻止时间冒泡,都应该包含在事件处理程序中
//改进的做法
var MyApplication = {
handleClick: function(event){
event.preventDefault();
event.stopPropagation();
this.showPopup(event.clientX,event.clientY);
},
showPopup: function(x,y){
var popup = document.getElementById('popup');
popup.style.left = x + 'px';
popup.style.top = y + 'px';
popup.className = 'reveal';
}
};
addListener(element,'click',function(event){
MyApplication.handleClick(event);
});
感觉这个需要日积月累,感觉前面是有无数的坑等着你踩先完成功能然后再考虑优化的问题
线程和进程的区别
node进程启动过后默认会创建一个线程,线程用于执行我们的代码
一个进程可以有多个线程,所有进程与线程是包含与被包含的关系
进程(程序):一个静态概念,一个class文件,一个exe文件
线程:是一个程序里面不同的执行路径
二叉树遍历
先序遍历:顺序根左右
中序遍历:顺序左根右
后序遍历:顺序左右根
层序遍历:顺序从上到下从左到右分层遍历
前序遍历:先访问根节点,然后前序遍历左子树,再前序遍历右子树(中左右)
中序遍历:从根节点开始(注意不是先访问根节点),中序遍历根节点的左子树,然后是访问根节点,左后遍历根节点的右子树(左中右)
这里还是要多罗嗦一些东西,因为我有时还是有点不太懂(这样是不是稍微清晰了一点)
中序遍历:BDCAEHGKF
后序遍历:从左到右先叶子后节点的方式遍历访问根节点(左右中)//怎么有点像css遍历从上到下从右到左
层序遍历:从树的第一层,也就是根节点开始访问,从上到下逐层遍历,在同一层中,按从左到右的顺序结构访问
浏览器的渲染原理
当浏览器获取html文件时,会"自上而下"加载,并在加载过程解析渲染
解析:
浏览器会将HTML解析成一个DOM树,DOM树的构建过程是一个深度遍历过程:当前节点的所有子节点都构建好后才会去构建当前节点的下一个兄弟节点
将CSS解析成CSS Rule Tree
根据DOM树和CSSOM树来构造Rendering Treen,注意:Rendering Tree渲染树并不等同于DOM树,因为一些想header或display:none的东西就没必要放在渲染树中
有了Render Tree,浏览器已经能知道网页中有哪些节点.各个节点的CSS定义以及他们的从属关系,下一步操作称之为Layout就是计算出每个节点在屏幕中的位置
然后就进行绘制,遍历render树,并使用UI后端层绘制每一个节点
终于说到重点了,影响浏览器渲染主要有:reflow(回流)和repaint(重绘)
回流Reflow(渲染机制类)
- DOM结构中的各个元素都有自己的盒子模型,这些需要浏览器根据各种样式计算并根据计算结果将元素放在该出现的位置,这个过程称reflow
触发Reflow
移动DOM
修改CSS
修改网页默认字体
增加删除修改DOM节点
重绘Repaint
- 页面呈现的内容放在页面上
触发Reqaint
DOM改动
CSS改动
尽量避免reflow(回流)
reflow想想怎么可能避免呢?那只能将reflow对性能的影响减到最小
比如需要改变元素的样式,不要通过父级元素影响子元素,最好直接加载子元素
设置style属性改变样式的话,没设置一次都会导致一次reflow,最好就是设置class的方式
避免不必要的复杂的css选择器,尤其是后代选择器(这里肯定会有人反驳了,我用的是less,就看看解析的时候,后代有多长,看着多怕,哥们要不你用sess或者sass,有个属性可以直接跳出选择器
@at-root
less有没有我也不知道)还有就是不要用tables布局
ES6
从数组中移出falsey值
使用Array.filter()删选出falsey值(false,null,0,"",undefined和NaN)
const compact=arr=>arr.filter(Boolean); console.log(compact([0, 1, false, "", 3, "s","e"*23,"a", NaN]));
计算数组中值的出现次数
使用Array.reduce()在每次遇到数组中的特定值时递增计数器
const coumt=(arr,value)=>arr.reduce((a,v)=>v===value?a+1:a+0,0); console.log(coumt([12, 1, 1, 2, 3, 4, 32, 2, 1, 1, 1, 1, 1], 1));
如果不理解逗号后面的值,可以再MDN查询
reduce
深度拼合数组
const deepFlatten = arr => [].concat(...arr.map(v => Array.isArray(v) ? deepFlatten(v) : v)); console.log(deepFlatten([1, [2], [[3], 4], "a"]));
注意SEO
合理的title,description,keywords:搜索对着三项的权重逐个减小,
语义化的HTML代码
重要内容HTML代码放在最前
重要内容不要用js输出
少用iframe
非修饰性图片必须加alt
提高网站速度
离线存储
在线的情况,会请求html的manifest属性,它会请求manifest文件的内容,根据内容进行离线存储,让加载页面时,会对新的manifest文件内容进行比较,进行存储
离线的情况,直接使用离线存储的资源
缺点:
更新的资源,需要二次刷新才会被页面采用
不支持增量更新,只有manifest发生变化,所有资源全部重新下载一次
缺乏足够容错机制,当清单中任意资源文件出现加载异常,都会导致整个manifest策略运行异常
在javascript中一切都是对象吗?
基本类型:
Boolean Null Undefined string number Symbol(E6)
对象类型: Object
- 数据封装类对象:
Object, Array ,Boolean, Number ,String
- 其他对象:
Function, Arguments ,Math, Date, RegExp,Error
- 任何非基本类型的都是对象类型
区别
基本类型
- 不可变,无法添加删除属性;按值比较,按值传递
对象类型
- 可变,支持添加删除属性,按引用比较,按引用传递
检测对象类型?或者检测一个数据是数组类型
Object.prototype.toString.call([])
typeof只在基本类型的检查上面才好使,在引用类型(Function除外) 里面他返回的都是object
Ajax
感觉我会写好多东西呀,可以当做复习哦,面试的时候说个一二十分钟不是问题
$.ajax({//jQuery
url:"http://www.baidu.com",//请求的url地址
dataType:"json",//返回的数据格式
data:{} //参数
type:"GET"
success:function(data){
//请求成功的请求
}
})
// 1.创建
var ajax = new XMLHttpRequest();
// 2设置
ajax.open('get', 'Ajax_get.php');
// 3.发送
ajax.send(null);
// 4.状态事件
ajax.onreadystatechange = function() {
if (ajax.readyState == 4 && ajax.status == 200) {
// 5.使用返回的数据 修改页面的内容
// responseText 返回的就是一个 字符串
// 我们 在ajax 中 如果 是通过 ajax.responseText 获取到的 统统都是字符串
console.log(ajax.responseText);
}
}
var ajax = new XMLHttpRequest();
// 使用post请求
ajax.open('post','ajax_post.php');
// 如果 使用post发送数据 必须 设置 如下内容
// 修改了 发送给 服务器的 请求报文的 内容
// 如果需要像 HTML 表单那样 POST 数据,请使用 setRequestHeader() 来添加 HTTP 头。然后在 send() 方法中规定您希望发送的数据:
ajax.setRequestHeader("Content-type","application/x-www-form-urlencoded");
// 发送
// post请求 发送的数据 写在 send方法中
// 格式 name=jack&age=18 字符串的格式
ajax.send('name=jack&age=998');
// 注册事件
ajax.onreadystatechange = function () {
if (ajax.readyState==4&&ajax.status==200) {
console.log(ajax.responseText);
}
}
function getXhr() {
var xhr = null;
if (window.XHLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveXObect("Microsoft.XMLHttp");
}
return xhr;
}
这个为什么我会单独写出来创建的对象兼容因为这里涉及到:
js高阶编程技巧之"惰性思想":能够执行一次就搞定的绝对不会执行多次
Ajax:asyncjavascript and xml 异步的js和XML
客户端js中的方法,用来向服务器端发送请求(还可以传递给服务器端数据,然后把服务器端返回的内容获取
xml:可扩展的标记语言(在xml文件使用的标签都是自己扩展的)
利用自己扩展的有规则的标记来存储相关的数据(xml后台用处很大)
xhr.readyState:请求状态码
0 (未初始化)当前的请求还没有发送
1 (载入)url地址已经打开(发送前的参数配置已经完成)
2(载入完成) 响应头信息已经接收
3(交互) 主要返回的内容正在服务器端进行准备处理
4(完成) 响应主体的内容已经成功返回到客户端
xhr.status:HTTP网络状态码,描述了服务器响应内容的状态
200 表示响应主体的内容已经成功返回了
301->永久重定向/永久转移
302->临时重定向/临时转移 服务器的负载均衡 304 本次获取的内容是读取缓存中的数据 400 客户端传递给服务器端的参数出现错误 401 无权限访问 404 客户端访问的地址不存在 500 未知的服务器错误 501->服务器已经超负荷 一台服务器能承受10000人,那么第10001个人访问,如果没有做服务器的负载均衡,那么这个人的状态码就是503
GET和POST的区别
get是从服务器获取数据----"取";post是向服务器提交数据---"发"
大小问题
GET请求传递给服务器的内容存在大小限制,而POST理论上没有限制
原因:GET通过URL传参给服务器,HTTP协议没有对URL长度进行限制,但是每个浏览器对于URL的长度存在限制,谷歌8k,火狐7kb,IE2kb,如果URL的长度超过限制,浏览器会把超出的部分截取
缓存的问题
GET请求会出现缓存(这个缓存不一定是304),POST是没有缓存的
在项目中我们的GET请求一般不会让其出现缓存"清除缓存":在URL的末尾追加一个随机数
xhr.open("get","/getList?num=12&="+Math.random()")
if (ajax["type"].toLowerCase() === "get") {
//->GET请求还需要在URL的末尾追加随机数
var suffix = ajax["url"].indexOf("?") > -1 ? "&" : "?";
ajax["url"] += suffix + "_=" + Math.random();
}安全问题 * 一般来说GET不安全,但是POST相对安全些
var xhr=new XMLHttpRequest(); xhr.open("get", "./vue.html"); xhr.send(null); xhr.onreadystatechange=function () { console.log(xhr.readyState);//没有任何输出 //输出的2,3,4因为在存储的时候就已经把0,1已经执行了,也就是说在前面就已经把0,1都已经执行了 }
垃圾回收机制
js的垃圾回收机制是为了以防止内存泄露,内存泄露的含义就是当已经不需要某块内存是这块内存还存在着,垃圾回收机制就是间歇的不定期的寻找不在使用的变量,并释放掉它们所指向的内存
变量的生命周期
- 当一个变量的生命周期结束之后它所指向的内存就应该被释放,JS有两种变量,全局变量和在函数产生的局部变量,当局部变量的生命周期在函数执行过后就结束了,此时便可被它引用的内存释放(立即回收),但全局变量生命周期会持续到浏览器关闭页面
回收方式:标记清除.引用技术(不常用)
标记清除
- 大部分浏览器以此方式进行垃圾回收,当变量进入执行环境(函数中声明变量)的时候,垃圾回收器将其标记为"进入环境",当变量离开环境的时候(函数执行结束)将其标记为"离开环境",在离开环境之后还有的变量则是需要被删除的变量
- 垃圾收集器给内存中的所有变量都加上标记,然后去掉环境的变量以及被环境中的变量引用的变量的标记,在此之后再被标记的变量极为需要回收的变量极为需要回收的变量,因为环境中的变量无法访问到这些变量
引用技术
引用技术的含义就是跟踪记录每个值被引用的次数
跨域问题
什么是跨域
只要协议,域名,端口有任何一个不同,就是跨域
为什么不能跨域
浏览器的同源策略,用来保护用户的安全
跨域的解决方案
JSONP
浏览器可以引用不同域下的JS文件,利用这个特性,实现跨域
get请求
callback参数
document.domain
页面地址是
http://a.baidu.com
,嵌入的iframe是http://b.baidu.com/
分别始终hi页面和iframe的
document.domain
为:baidu.com就可以解决
CORS方案
CORS定义一种跨域访问的机制,可以让AJAX实现跨域访问,CORS允许一个域
向另一个域提交跨域的ajax请求
header("Access-Control-Allow-Origin","*")
post请求
反向代理
正向代理代理的对象是客户端,
反向代理代理的对象是服务器
使用HTML5引进的window.postMessage
方法来跨域
个人认为
window.name
的方法既不复杂也能兼容所有的浏览器
HTTP和HTTPS有何差异
HTTP:相对HTTPS来说,速度较快且开销较小,默认是80端口
HTTPS相对安全但开销较大(数据以加密的形式传递),默认端口443
HTTP是明文跑到TCP上,而HTTPS跑在SSL/TLS应用层之下,TCP上
HTTPS
- 非对称加密,生成公钥和私钥
- 更严谨的采用CA,给密钥签名
变态题
var count = 0;
console.log(typeof count === "number"); // true , 这个不用解释了
console.log(!!typeof count === "number"); // false
// 这里涉及到就是优先级和布尔值的问题
// typeof count 就是字符串"number"
// !!是转为布尔值(三目运算符的变种),非空字符串布尔值为 true
// 最后才=== 比较 , true === "number" , return false
(function(){
var a=b=3;
//var a,a=b; b=3跑到全局去了
})()
null instanceof Object //false 两个都不熟悉一个数据类型
var val = 'smtg';
console.log('Value is ' + (val === 'smtg') ? 'Something' : 'Nothing'); //+的优先级大于等于号
javascript中不容易分清的slice 和splice
slice()
根据索引值和索引值截取字符串(若截取数组,不改变原数组)
slice(1,2) //从第0项开始,包左不包右
slice(-3) //从后往前截取到倒数第三个
slice(5,2)/返回空字符
splice() 截取数组,不能截取字符串
splice(1,2) //改变原数组 ,从0项开始删除
1,2项
splice(1,2,"aaa","bbb") //替换
1,2的值
splice(1,0,"aaa","bbb") //在键值对为1的前面插入
两个值 ,第二个参数为0就是不替换参数,1就是替换一个参数
jS的闭包
函数声明的时候,会生成一个独立的作用域
同一作用域的对象可以互相独立访问
作用域呈现包含状态,形成作用域链,子作用域的对象可以访问父作用域的对象,反之不能;
另外子作用域会使用最近的父作用域的对象
闭包是函数
作为内部函数保存着对外部函数中变量的引用
页面加载
加载一个资源的过程
- 浏览器根据DNS服务器得到域名的IP地址
- 向这个IP的机器发送http请求
- 服务器收到,处理并返回http请求
- 浏览器得到返回内容
浏览器渲染页面的过程
- 根据HTML结构生成DOM Tree
- 根据css生成CSSOM
- 根据DOM和CSSOM整合形成RenderTree
- 根据RenderTree开始渲染和展示
- 遇到script标签时,会执行并阻塞渲染
前端网页有那三层构成,分别是什么?作用是什么
- 结构层HTML,决定网页的结构
- 表示层CSS,决定网页的样式
- 行为层JS,决定网页的行为
什么样的前端代码是好的
高复用低耦合,这样文件小,好维护,而且好扩展
请解释什么是事件委托
是把原本需要绑定的事件委托给父亲,让父元素担当事件监听的职务
简单的说就是某个时间本来该自己干的,但是自己不干,交给别人来干,就交
<ul id="ul1">
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
实现功能是点击li,弹出123:
复制代码
window.onload = function(){
var oUl = document.getElementById("ul1");
var aLi = oUl.getElementsByTagName('li');
for(var i=0;i<aLi.length;i++){
aLi[i].onclick = function(){
alert(123);
}
}
}
优点可以提高性能
通过HTTP请求响应过程了解HTTP协议
DNS域名解析
发起TCP的3次握手
简历TCP连接后发起http请求
服务器端响应http请求,浏览器得到html代码
浏览器解析html代码,并请求html代码中的资源
浏览器对页面进行渲染呈现给用户
发起TCP的3次握手
在客户端和服务器之间建立正常的TCP网络连接是
客户端发送SYN给服务器
服务端返回SYN+ACK给客户端
客户端确认,返回ACK给服务端
超易错的CSS优先级关系
.classB{
background-color: red;
}
.classA{
background-color: rebeccapurple;
}
</style>
<!--与样式定义的前后有关--与标签的class顺序无关-->
<p class="classA classB">1111111</p>
H5与APP混合开发遇到的问题
页面滚动条问题
web页面在pc浏览时有滚动条,但是在移动端浏览器打开时,没有滚动条
解决方法
给body一个大容器 设置
overflow:auto/scroll
其他的兼容性就不说了,看着脑袋疼,解决方案等遇到了再解决吧
说说你对vue声明周期的理解
分为8个阶段,创建前/后,载入前/后,更新前/后,销毁前/后
- 创建前/后:在beforeCreate阶段,vue实例的挂载元素,el和数据对象data都是undefined,还没初始化,在created阶段,用于发生数据请求,也可以初始化一些数据
- 载入前后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点上,data.message还没有替换,在mounted阶段,vue实例挂载完成,data.message成功渲染
- 更新前后:当data变化时,出触发beforeUpdata和updated方法
- 销毁前后:在执行destroy方法后,对data 的改变不会在触发周期函数,说明vue实例已经接触了事件监听以及dom的绑定,但是dom结构依然存在
父组件如何将数据传到子组件
- 父组件可以通过props传递数据到子组件中
- props是单向绑定的
- 每次父组件更新是,子组件的所有props都会更新为最新值
子组件如何将数据传到父组件
- 子组件可通过vm.$emit将数据传递到父组件
- vm.$emit是触发当前实例上的事件,附加参数都会传给监听器回调
面向对象编程的三个基本特性
封装.继承,多态
封装
- 也就是把客观事物封装成抽象的类
- 并且类可以把自己的数据和方法只让可信的类或者对象操作
- 对不可信的进行信息隐藏
继承
- 它可以使用现有类的所有功能,并在无需编写原来的类的情况下对这个类的情况下对这些功能进行扩展
- 要实现继承,可以通过"继承"和"组合"来实现
多态
- 后端的,js没有这个概念
总结
- 封装可以隐藏实现细节,使得代码模块化,继承可以扩展已存在的代码模块(类)
- 目的是为了--代码重用
javascript实现继承的方式
-
原型链继承(父类的实例作为子类的原型)
- 缺点
- 来自原型对象的引用属性是所有实例共享的
- 创建子类实例时,无法向父类构造函数传参
-
构造继承(复制父类的实例属性给子类)
- call/apply/bind
- 缺点:无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
-
实例继承
- 为父类实例添加新特性,作为子类实例返回
-
拷贝继承
- cat.prototype[p]=animal[p]
- 缺点:效率较低,内存占用高
-
组合继承
- 通过调用父类构造,继承父类的属性并保留传参的有点,然后通过将父类实例作为子类原型,实现函数复用
-
寄生组合继承
- 通过寄生方式,砍掉父类的实例属性(new),这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性
promise
解决回调问题
最大的好处就是在异步执行的流程中,把执行代码和处理结果的代码清晰的分离
promise有三种状态:等待(pending ). 已完成(fulfilled /f斐o/). 已拒绝(rejected /v jk/)
一个promise的状态之可能从"等待"转到"完成"或者"拒绝",不能逆向转移
promise本质就是一个函数,他可以接受一个函数作为参数,并且会返回promise对象
promise.then(function(value) {
// 如果调用了resolve方法,执行此函数
}, function(value) {
// 如果调用了reject方法,执行此函数
});
promise.then(function(result) {
//成功时的处理
}).catch(function(error) {
//错误时的处理
})
resolve /v 肉/
webpack的loader是干什么的
loader是用来编译和处理资源的
loader用于对模块的源代码进行转换,loader可以使你在import或"加载"模块是预处理文件,因此,loader类似于其他构建工具中"任务(task)",并提供了处理前端构建步骤的强大方法
当我们遇到大问题时,首相想到的总是去搜搜看有没有现成的解决方案,但现实却难免是没有解决问题,在这种情况下,我们也可以尝试去写一些插件,组件,或者一个通用化的解决方案,来解决自身的问题,同时对自己掌握一些知识也会有帮助,而且尝试过后可能发现,他也没这么难
Vue组件的data属性为什么是函数
每个组件都是Vue的实例,每个组件都应该有自己作用域
函数拥有自己的作用域,可以避免组件共享data属性
Vue的路由怎么实现的
路由:直接找到与地址匹配的组件,并将其渲染出来,改变浏览器地址,但不请求服务器
实现方式:地址中添加#来欺骗浏览器,地址的改变是进行页面内导航
Vue router与location.href的区别
vue router是hash值改变,页面内跳转
location.href是页面跳转,页面刷新
Webpack与Gulp的区别
Gulp是一种能够优化前端代码的开发流程的工具
webpack是一种模块化的解决方案
plugins(插件)
plugins并不是直接操作单个文件,他直接对整个构建过程起作用
比如他会将入口引用css文件,都打包独立的css文件,而不是内嵌在js打包文件中
call 和apply的区别是什么
obj.call(thisObj,arg1,arg2)
obj.apply(thisObj,[arg1,arg2])
两者作用一致,都是把obj(this)绑定到thisObj
,这时候thisObj
具备了obj的属性和方法
区别是call接受的是连续参数,apply接受的是数组参数
typeof和instanceof
typeof用于判断基本类型,是一元运算符.返回结果是字符串
undefined .boolean .null.string.number.symbol.function.object
instanceof用于判断对象的类型,是二元运算符.返回结果是布尔值
注意:基本类型与一些特殊类型无法得到真的结果
三角形的实现原理
#aaa{
width: 0;
height: 0;
border:20px solid transparent;
border-bottom-color:red;
}
AMD与CMD
AMD:异步模块定义,所有模块异步加载,模块加载不影响后续运行,所有依赖模块的语言必须写在回调函数中,提前执行依赖前置主要应用于require.js 一个当多个用
CMD:同步加载 延迟执行 依赖就近,主要应用sea.js推荐每一个模块职责单一
判断一个参数是否是一个数组
instanceof方法主要检测 变量的constructor是否与Array相等,也就是检测变量的原型链是否指向Array构造函数的prototype原型上
arr instanceof Array
arr.constructor ===Array
Array.isArray()
Object.prototype.toString.call(arr)
什么是原型链
javascript是面向对象的,每个实例对象都有一个
__proto__
属性,该属性指向它原来对象,这个实例对象的构造函数有一个原型属性prototype,与实例的__proto__
属性指向同一个对象,当一个对象在查找一个属性的时,自身没有就会根据__proto__
向它的原型进行查找,如果都没有,则想他的原型的原型继续查找,直到查到Object.prototype.__proto__
为null,这样也就形成原型链
日常变态题点我
让自己对原生js又多了一点点小小的认识
false==0
true==1
this是如何工作的
this永远指向函数运行时所在的对象,而不是函数被创建是所在的对象,匿名函数或者不处于任何对象中的函数指向window
如果call .apply.bind ,指定的this是谁,就是谁
普通的函数调用,函数被谁调用,this就是谁
决定自己的高度的是你的态度,而不是你的才能
记得我们是终身初学者和学习者
总有一天我也能成为大佬