备战秋招,复习基础。若有错误,欢迎批评指正,共同进步!javascript
整理自本身的面试经验+网络资料css
部分资料参考自网络,在具体内容前均有标出~感恩你们~html
因为篇幅缘由,拆成两篇~前端面试梳理(一)前端
参考资料:JavaScript 的 this 原理java
参考资料:JS this指向总结ios
在函数体内部,指代函数当前的运行环境。css3
哪一个对象调用函数,函数里面的this指向哪一个对象。web
let username='cn'
function fn(){
alert(this.username);//undefined
}
fn();
复制代码
window.b=2222
let obj={
a:111,
fn:function(){
alert(this.a);//111
alert(this.b);//undefined
}
}
obj.fn();
复制代码
let TestClass=function(){
this.name='111';
}
let subClass=new TestClass();
subClass.name='cn';
console.log(subClass.name);//cn
let subClass1=new TestClass();
console.log(subClass1.name)//111
复制代码
let obj1={
a:222
};
let obj2={
a:111,
fn:function(){
alert(this.a);//222
}
}
obj2.fn.call(obj1)
复制代码
let obj={
a:222,
fn:function(){
setTimeout(function(){console.log(this.a)})
}
};
obj.fn();//undefined ← 传给setTimeout的是普通函数,this 指向是 window
let obj={
a:222,
fn:function(){
setTimeout(()=>{console.log(this.a)});
}
};
obj.fn();//222 ← 传给setTimeout的是箭头函数,setTimeout的上层做用域是fn。fn里面的this指向 obj,因此setTimeout里面的箭头函数的this指向obj。
复制代码
1. 箭头函数是匿名函数,不能做为构造函数,不能使用new
2. 箭头函数不绑定arguments,取而代之用rest参数...解决
3. 箭头函数不绑定this,会捕获其所在的上下文的this值,做为本身的this值
4. 箭头函数经过call()或apply()方法调用一个函数时,只传入了一个参数,对this并无影响。
5. 箭头函数没有原型属性
6. 箭头函数不能当作Generator函数,不能使用yield关键字
复制代码
参考资料:js中的new()到底作了些什么??面试
建立一个新对象,将新对象的_proto_指向构造函数的原型对象,而后将构造函数的this指向新对象。调用构造函数。ajax
1. 建立一个新对象;
2. 将构造函数的做用域赋给新对象(所以 this 就指向了这个新对象) ;
3. 执行构造函数中的代码(为这个新对象添加属性) ;
4. 返回新对象。
复制代码
参考资料:完全搞懂JS闭包各类坑
闭包:可以访问另外一个函数做用域的变量的函数。
function outer() {
var a = '变量1'
var inner = function () {
console.info(a)
}
return inner // inner 就是一个闭包函数,由于他可以访问到outer函数的做用域
}
复制代码
因为闭包会携带包含它的函数的做用域,由于会比其余函数占用更多内容,过分使用闭包,会致使内存占用过多。
参考资料:帮你完全搞懂JS中的prototype、__proto__与constructor(图解)
1. __proto__和constructor属性是对象所独有的;
2. prototype属性是函数所独有的,由于函数也是一种对象,因此函数也拥有__proto__和constructor属性。
3. __proto__属性的做用就是当访问一个对象的属性时,若是该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(父对象)里找,一直找,直到__proto__属性的终点null,再往上找就至关于在null上取值,会报错。经过__proto__属性将对象链接起来的这条链路即咱们所谓的原型链。
4. prototype属性的做用就是让该函数所实例化的对象们均可以找到公用的属性和方法,即f1.__proto__ === Foo.prototype。
5. constructor属性的含义就是指向该对象的构造函数,全部函数(此时当作对象了)最终的构造函数都指向Function。
复制代码
let data = [];
$.ajax({
url:www.javascript.com,
data:data,
success:() => {
console.log('发送成功!');
}
})
console.log('代码执行结束');
1. ajax进入Event Table,注册回调函数success。
2. 执行console.log('代码执行结束')。
3. ajax事件完成,回调函数success进入Event Queue。
4. 主线程从Event Queue读取回调函数success并执行。
复制代码
macro-task(宏任务):包括总体代码script,setTimeout,setInterval
micro-task(微任务):Promise,process.nextTick
setTimeout(code,等待毫秒数)
屡次调用: 1 code自身再次调用setTimeout()
2 用setInterval(code,时间间隔)
复制代码
1. 定义图片路径数组存放图片路径。定义字符串数组存放文字描述。
2. 封装prev和next方法
3. 绑定按钮的点击事件
复制代码
具体含义待补充!!!
1 var fn1 = function(){
}();
2 (function (){
}());
3 (function(){
}();
4 !function(){
}();
5 +function(){
}();
复制代码
==
先转换再比较 bolean → 数值
对象 → valueOf()/toString()
字符串 → 数值
===
不转换直接比较 null===undefined//false
object.is(a,b)
比较规则与===
相同比较 | == | === | object.is() |
---|---|---|---|
null undefined | true | false | false |
NaN NaN | false | false | true |
undefined 0 | false | false | false |
null 0 | false | false | false |
-0 +0 | true | true | false |
Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};
let arr = ['a','b','c'];
arr.hobby = 'foosball';
for (let i in arr) { ← for in 用键key遍历
console.log(i); // 0, 1, 2, "hobby", "arrCustom", "objCustom" ← 可循环出自定义的属性
}
for (let i in iterable) {
if (iterable.hasOwnProperty(i)) {
console.log(i); //0, 1, 2, "hobby" ← 过滤非实例属性
}
}
for (let i of iterable) { ← for of 用值value遍历
console.log(i); // 'a', 'b', 'c' ← 无自定义属性
}
for(var key of Object.keys(arr)){ ← 使用Object.keys()方法获取对象key的数组
console.log(arr[key]);
}
复制代码
1. typeof 返回number/boolean/symbol/string/object/undefined/function
2. instanceof 判断A是否是B的实例
3. constructor [].constructor == Array //true
4. toString Object.prototype.toString.call([]);
其中差别待补充!!!
复制代码
参考资料:ES6中的类继承和ES5中的继承模式详解
ES5的继承,实质是先创造子类的实例对象this,而后再将父类的方法添加到this上面(Parent.apply(this))。
ES6的继承机制彻底不一样,实质是先创造父类的实例对象this(因此必须先调用super方法),而后再用子类的构造函数修改this。
类的继承能够看作是寄生组合式继承的语法糖
Object.freeze
操做一个对象后, 就会使这个对象不能够新增属性, 删除属性, 对于已经存在的属性也不能够从新配置(The descriptor for the property), 或者被修改.若是属性是一个对象值的, 那么这个属性仍是能够被修改的, 除非再次让这个属性为 freeze.
缺陷:freeze 操做只是针对于 window.openApi 对象自己, 而非针对 window 对象自己, 因此你仍旧能够从新定义 window 的 openApi 属性.
复制代码
经过 Object.defineProperty
分别设置其 configurable 和 writable 为 false.
<script type="text/javascript">
//方法一
function sleep1(ms, callback) {
setTimeout(callback, ms)
}
//sleep 1s
sleep1(1000, () => {
console.log(1000)
})
//方法二
function sleep2(ms) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, ms)
})
}
sleep2(1000).then(() => {
console.log(2000)
})
//方法三
function sleep3(ms) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, ms)
})
}
async function init() {
await sleep3(1000);
}
init().then(() => {
console.log(3000)
})
</script>
复制代码
参考资料:对js数组的splice实现
Array.prototype.splice = function(start,deleteCount){
var max = Math.max,
min = Math.min,
delta,
element,
insertCount = max(arguments.length - 2,0), //插入的元素的个数,最小为0
k = 0,
len = this.length,
new_len,
result = [], //返回的数组,包函了被删除的元素
shift_count;
start = start || 0; //如何start不存在,则从0开始
if(start < 0){
start += len; //确保start为正数
}
start = max(min(start,len),0); //确保start为正数
deleteCount = max(min(typeof deleteCount === 'number' ? deleteCount : len,len-start),0); //要删除元素的个数
// 1.若是deleteCount存在则deleteCount,不然len
// 2.用1的结果与len-start对比,取较小者(由于最大可删除的元素个数为len-start)
// 3.用2的结果与0比对,取大者,防止为负数
delta = insertCount - deleteCount;
alert(delta);
/*
* 1.若是delta大于0,说明数组长度会增长
* 2.若是delat小于0,说明数组长度会减小
*/
new_len = len + delta; //数组的新长度
while(k < deleteCount){ //这个while循环的做用是保存要返回的result,即保存被删除的元素
element = this[start + k];
if(element != undefined){
result[k] = element;
}
k++;
}
shift_count = len - start - deleteCount;
/*
* 1. len-start ,start前端的元素不用动
* 2. 用1的结果再减去deleteCount,是start后面要保留的元素的个数
* 3. 经过shift_count次的遍历,就能够把要保留的元素向前移动,达到删除的目的
*/
if(delta <= 0){ //在数组长度减小的状况下
k = start + insertCount; //k的初始下标为要保留的元素新的开始下标
while(shift_count){
this[k] = this[k - delta]; //后面的替换前面的要删除的元素
k += 1;
shift_count -= 1;
}
this.length = new_len;
}else if(delta > 0){ //在数组长度增长的状况下
k = 1;
while(shift_count){
this[new_len - k] = this[len - k]; //从数组的最后一个元素开始,倒着进行替换
k += 1;
shift_count -= 1;
}
this.length = new_len;
}
for(k = 0; k < insertCount; k+=1){
this[start + k] = arguments[k+2]; //插入替换元素
}
return result;
};
复制代码
var divE = document.createElement('div');
var divId = document.createAttribute("id");
divId.value = 'name';
divE.setAttributeNode(divId); //为节点添加属性
复制代码
Object(原型类名).prototype.sss = function(){
console.log(this);
}
复制代码
寄生组合式继承:经过借用构造函数来继承属性,经过原型链的方式来继承方法,而不须要为子类指定原型而调用父类的构造函数,咱们须要拿到的仅仅是父类原型的一个副本。所以能够经过传入子类和父类的构造函数做为参数,首先建立父类原型的一个复本,并为其添加constrcutor,最后赋给子类的原型。这样避免了调用两次父类的构造函数,为其建立多余的属性。
//父:person
function Person(name){
this.name=name;
}
Person.prototype.sayName=function(){
console.log(this.name+' '+this.gender+' '+this.age);
}
//借用构造函数来继承属性的方法
function inheritPrototype(Female,Person){
var protoType=Object.create(Person.prototype);
protoType.constructor=Female;
Female.prototype=protoType;
}
//调用继承方法
inheritPrototype(Female,Person);
//子:female 新增方法
Female.prototype.sayAge=function(){
console.log(this.name+' '+this.age);
}
//尝试调用
var fm=new Female('skila','female',19);
fm.sayName();//skila female 19
fm.sayAge();skila 19
复制代码
1. 不会当即执行函数,须要返回一个待执行的函数
2. 做用域绑定,使用apply或者call方法
3. 参数传递,因为参数的不肯定性,用apply传递数组
复制代码
Function.prototype.bind = function(newThis) {
var aArgs = Array.prototype.slice.call(arguments, 1) //拿到除了newThis以外的预置参数序列
var that = this
return function() {
return that.apply(newThis, aArgs.concat(Array.prototype.slice.call(arguments)))
//绑定this同时将调用时传递的序列和预置序列进行合并
}
}
复制代码
<html>
<head>
<script type="text/javascript">
var c=0
var t
function timedCount()
{
document.getElementById('txt').value=c
c=c+1
t=setTimeout("timedCount()",1000)
}
function stopCount()
{
clearTimeout(t)
}
</script>
</head>
<body>
<form>
<input type="button" value="Start count!" onClick="timedCount()">
<input type="text" id="txt">
<input type="button" value="Stop count!" onClick="stopCount()">
</form>
</body>
</html>
复制代码
function isObj(obj) {
//判断是否为对象或者函数,但不是null
return (typeof obj === 'object' || typeof obj === 'function') && obj !== null
}
function deepCopy(obj) {
let newObj = Array.isArray(obj) ? [] : {}
for(let key in obj) {
newObj[key] = isObj(obj[key]) ? deepCopy(obj[key]) : obj[key]
}
return newObj
}
或
函数库lodash,提供_.cloneDeep()
复制代码
function getQuery(name) {
// 正则:[找寻'&' + 'url参数名字' = '值' + '&']('&'能够不存在)
let reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
let r = window.location.search.substr(1).match(reg);
if(r != null) {
// 对参数值进行解码
return unescape(r[2]);
}
return null;
}
// 调用方法,注意须要传入String类型的数据,输出结果为String类型
getQuery('id'); // '123'
复制代码
function isPoneAvailable($poneInput) {
var myreg=/^[1][3,4,5,7,8][0-9]{9}$/;
if (!myreg.test($poneInput.val())) {
return false;
} else {
return true;
}
}
复制代码
var arr = [1, 2, 3, 4, 5];
arr.sort(functon() {
return Math.random() - 0.5;
})
复制代码
参考资料:javascript判断两个IP地址是否在同一个网段的实现思路
要判断两个IP地址是否在同一个网段,将它们的IP地址分别与子网掩码作与运算,获得的结果为网络号,若是网络号相同,就在同一子网,不然,不在同一子网。
function isEqualIPAddress (addr1,addr2,mask){
if(!addr1 || !addr2 || !mask){
console.log("各参数不能为空");
return false;
}
var res1 = [], res2 = [];
addr1 = addr1.split(".");
addr2 = addr2.split(".");
mask = mask.split(".");
for(var i = 0,ilen = addr1.length; i < ilen ; i += 1){
res1.push(parseInt(addr1[i]) & parseInt(mask[i]));
res2.push(parseInt(addr2[i]) & parseInt(mask[i]));
}
if(res1.join(".") == res2.join(".")){
console.log("在同一个网段");
return true;
}else{
console.log("不在同一个网段");
return false;
}
}
复制代码
function indexOf(str, val){
var strLen = str.length, valLen = val.length
for(var i = 0; i < strLen; i++){
var matchLen = i + valLen
var matchStr = str.slice(i, matchLen)
if(matchLen > strLen){
return -1
}
if(matchStr === val){
return i
}
}
return -1
}
复制代码
Function.prototype.call2 = function (context) {
var context = Object(context) || window
context.fn = this
var args = []
for (var i = 1; i < arguments.length; i++) {
args.push('arguments[' + i +']')
}
var res = eval('context.fn(' + args + ')')
delete context.fn
return res
}
复制代码
盒模型:包含了元素内容(content)、内边距(padding)、边框(border)、外边距(margin)几个要素。
用途:
1 对文本的隐藏
2 隐藏超连接
3 对统计代码隐藏
4 隐藏超出的图片
5 CSS隐藏滚动条
6 CSS隐藏div层
方法:
1 display:none → 不占位置
2 overflow:hidden / visibility:hidden
3 opacity:0
4 position:absolute;top:-9999px;left:-9999px
复制代码
1. 双层 - 使用absolute定位居中
.container{
position:relative;
height:100px; ← 不然无高度,会向上偏移覆盖上方元素
}
.child{
transform:translate(-50%,-50%); ← 图像大小的一半
top:50%;left:50%; ← 容器位置的一半
position:absolute;
}
2. 双层 - 使用flexbox居中(主流)
.container{
display:flex;
justify-content:center;
align-items:center;
}
3. 双层 - 使用calc基于当前页面布局计算尺寸
.container{
position:relative;
height:100px; ← 没设定高度则找不到盒子
width:100px; ← 没设定宽度则默认页面居中
}
.child{ ← 使盒子居中,盒子内部不必定居中!
position:absolute;
width:40%;
height:40%;
top:calc(50%-20%);
left:calc(50%-20%);
}
45. 图片子元素
.child{
display:inline-block;
vertical-align:middle; ← 须要有一个兄弟文字元素 设置居中 使图片和文字的基线对齐
}
5. 双层 - margin auto 定位块级元素
.container{
height: 200px;
width: 200px;
position: relative;
}
.child{
margin: auto; ← 必须设定四周位置和宽高
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
height: 100px;
width: 100px;
position: absolute;
}
6. 单层 - 使用text-align水平居中(非垂直居中)
.container{
text-align:center;
}
7. 单层 - 单行文本元素 使用text-align水平居中 + line-height垂直居中
.div{
display: inline-block;
height: 100px;
line-height: 100px;
text-align: center;
width: 200px; ← 不设宽度的话,宽度自适应为文字宽度
}
8. 单层 - 多行文本元素
.div{
display:table-cell;
text-align:center;
vertical-align: middle;
}
复制代码
1. 传统盒模型布局方式:使用display(文档流)+position属性(定位布局)+float属性(浮动布局)
2. flex弹性布局:display:flex
3. Grid网格布局:实现二维布局 display:grid / inline-grid / subgrid
grid-template-columns 列宽 grid-template-rows 行高 有几个数字就几列/行
grid-column-gap 列与列的距离
4. 圣杯布局:两边定宽,中间自适应。
三个元素都是float:left
.left{margin-left:-100%}
.right{margin-left:-(width)px}
.mid{padding:width}
5. 双飞翼布局:与圣杯相似,只是中间防遮挡不一样
在中间的div内部建立子div放置内容,子div里用margin留出位置
复制代码
块级格式化上文,是一个独立的布局环境,其中的元素布局是不受外界影响。
position:absolute / fixed
或
display: inline-block / table-cell / table / caption
或
float != null / overflow != visible
复制代码
特性:
1 子元素margin重叠
2 会自动清除内部浮动
复制代码
防止外边距重叠解决方案:
1 外层元素padding代替
2 内层元素透明边框 border:1px solid transparent;
3 内层元素绝对定位 postion:absolute:
4 外层元素 overflow:hidden;
5 内层元素 加float:left;或display:inline-block;
6 内层元素padding:1px;
复制代码
如何解决子元素形成的父元素高度塌陷问题:
1 给父元素再添加一个高度为0的子元素,而且让它清除浮动【clear:both;】
2 给父元素设置display:inline-block;
3 给父元素设置overflow:hidden;
4 给父元素设置固定的高度
5 对父元素使用伪元素:after,而且清除浮动【clear:both;】
复制代码
px:绝对尺寸,不能适用浏览器缩放
em:相对尺寸,相对于当前对象内文本的font-size,但须要知道父元素文本的font-size和对象内文本的font-size
rem:相对尺寸,相对于根元素<html>的font-size
复制代码
参考资料:[margin-left: auto;为何可使的元素靠右](https://segmentfault.com/q/1010000008431088)
复制代码
div {
width: 100px;
margin-left: auto;
}
由于
'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' +'border-right-width' + 'margin-right' = width of containing block
因此
margin-left = width of containing block - width(div)
复制代码
当页面滚动超出设置距离时,改变样式属性 切换定位状态fixed,给top设置一个值
--- css ---
.box{
position: relative;
height: 80px;
width: 100%;
z-index: 999;
}
.box-active{
position: fixed;
top: 0;
}
--- js ---
// 监听事件
window.addEventListener('scroll', function(){
let t = $('body, html').scrollTop(); // 目前监听的是整个body的滚动条距离
if(t>0){
$('.box').addClass('box-active')
}else{
$('.box').removeClass('box-active')
}
})
复制代码
document.getElementsByTagName('body')[0].style.height = window.innerHeight+'px';
复制代码
html{
height:100%
}
body{
height:100%;
}
复制代码
为body设置高度,只是IE6下有做用。而代码中除了给body应用之外,还给html对象也应用了相同的样式。这样作的好处是使IE与Firefox都可以实现高度自适应。另外,FirefoxFirefox中的HTML标签不是100%高度,所以给两个标签都定义为height:100%;以保证两个浏览器下均可以正常显示。
无论中间内容怎么撑高,两边侧栏都会跟着等高
<style>
body{margin: 0;padding: 0;}
.wrap{
overflow: hidden; ← 必须的,不然会显示溢出的内容!
}
.left{
width: 200px;
background-color: #C5C5C5;
float: left;
margin-bottom: -3000px;
padding-bottom: 3000px;
}
.right{
width: 300px;
background-color: yellow;
float: right;
margin-bottom: -3000px; ← 使父级宽度不被撑开成3000px
padding-bottom: 3000px;
}
.main{
height: 500px;
background-color: lightpink;
margin: 0 310px 0 210px ;
}
</style>
复制代码
<div class="ellipse"></div>
<style>
.ellipse {
width: 400px;
height: 200px;
border-radius: 50%;
background-color: #000;
}
</style>
复制代码
<svg width="800" height="400">
<ellipse rx="200" ry="100" cx="400" cy="200"></ellipse>
</svg>
复制代码
<svg width="800" height="400" id="J_SvgWrap"></svg>
<script>
var svg = document.getElementById('J_SvgWrap');
var ell = document.createElementNS('http://www.w3.org/2000/svg', 'ellipse');
ell.setAttribute("cx", 400);
ell.setAttribute("cy", 200);
ell.setAttribute("rx", 200)
ell.setAttribute("ry", 100)
svg.appendChild(ell);
</script>
复制代码
<canvas width="800" height="400" id="J_MyCanvas"></canvas>
<script>
var cvs = document.getElementById('J_MyCanvas');
var ctx = cvs.getContext('2d');
ctx.scale(1, 0.5);
ctx.arc(400, 200, 200, 0, Math.PI * 2);
ctx.fill();
</script>
复制代码
1. 边框 border-radius box-shadow border-image
2. 背景 background-size background-origin
3. 文本效果 text-shadow word-wrap
4. 字体:CSS3 @font-face 规则能够自定义字体。
5. 2D 转换(transform)
6. 3D 转换
7. transition:过渡效果,使页面变化更平滑
8. animation:动画
复制代码
XHTML 元素必须被正确地嵌套。
XHTML 元素必须被关闭。
标签名必须用小写字母。
XHTML 文档必须拥有根元素。
复制代码
父:
this.state = {name:'xx'}
<Person data = {this.state.name}/>
子:
<div data = {this.porps.name}/>
复制代码
参考资料:Vue.js与React的全面对比
对比点 | 框架 | 区别 |
---|---|---|
数据流 | ||
- | Angular | 双向绑定。界面操做实时反映到数据,数据变动实时展示到页面 |
- | Vue | 默认单向绑定,经过依赖追踪支持双向绑定:经过 Object.defineProperty 把data对象的属性所有转为 getter/setter |
- | React | 函数式编程,单向数据流:在View层直接写JS代码Model层中的数据拿过来渲染 |
视图渲染 | ||
- | Angular | 在DOM加载后遍历生成NG指令 |
- | Vue | 使用真实DOM做为模板,数据绑定到真实节点,改变多少更新多少 |
- | React | 渲染虚拟DOM,再给真实DOM打补丁。超大量数据的首屏渲染有优点 |
事件绑定 | ||
- | html | onclick =" listen() "; |
- | Vue | @click = " listen($event,参数) "; |
- | React | onClick={this.deleteRow.bind(this, id) 或 onClick={(e) => this.deleteRow(id, e) |
数据获取 | ||
- | 原生js | var xhr = creatXHR(); |
- | Vue | axios.get(url).then(function(response){...}).catch(function(error){...}); |
- | React | axios/reqwest |
路由 | ||
- | Vue | <router-link to="/foo">Go to Foo</router-link> |
- | React | <Route path="/repos" component={Repos}/> |
开发模式 | ||
- | Vue | Vue是MVVM模式的一种方式实现 |
- | React | React自己,是严格的view层,MVC模式 |
待补充……!!!
H5是一个解决方案,是一系列技术的集合
1 页面预加载:使用createJS中的preloadJS
2 音乐加载播放:使用createJS中的soundJS
3 可滑动页面:swiper.js插件,touch系列事件
4 可涂抹擦除:使用canvas叠加层
5 动态文字和图片:css3动画和Js动画
6 可填表报名
7 分享自定义文案和图片:使用微信jssdk
8 包含:audio标签、canvas拖拽特性、本地存储、websocket通信、盒模型、绝对定位
复制代码
1 分辨率resolution适配:使用rem。针对不一样屏幕宽度,调整高宽比、文字大小、元素间距
2 单位英寸像素数PPI适配:标题用rem(会发虚),段落用px,用media query或Js适配
3 设备像素比例DPR适配复制代码