js基础知识
-
值传递,引用传递
对于数组和对象等是将对象(数组)的变量的值传递给了函数参数,这个变量保存的指向对象(数组)的地址。当函数改变这个地址指向的对象(数组)的内容时,同时也改变了函数外部变量指向的对象(数组)的内容;当函数改变的是变量的地址时,实际就与函数外部的变量失去了联系,变成了完全不同的对象了,不会对函数外部对象造成改变。
var v1 = [] var v2 = {}; var v3 = {}; function foo(v1, v2, v3) { v1 = [1]; v2 = [2]; v3 = {a:3} } foo(v1, v2, v3); alert (v1); // 空白 alert (v2); // [object Object] alert (v3.a); // undefined
由此可见:v1、v2、v3 都没有被改变,v1 仍然是零个元素的数组,v2、v3 仍然是空白的对象。
但是,数组、对象等按值传递,是指变量地址的值。
var v1 = []
var v2 = {};
var v3 = {a:0};
function foo(v1, v2, v3)
{
v1.push (1);
v2.a = 2;
v3.a = 3;
}
foo(v1, v2, v3);
alert (v1); // 1
alert (v2.a); // 2
alert (v3.a); // 3
this(会出题让你看结果)
this讲解
http://www.68kejian.com/page/study/course/80/468-
闭包(原理,setTimeout和改写,为什么用,优点缺点)
闭包
JS特殊的变量作用域----全局变量和局部变量。JS特殊之处,函数内部可以直接读取全局变量。有时候需要得到函数内的局部变量,只有通过变通方法才能实现。那就是在函数的内部,再定义一个函数
function f1(){ n=999; function f2(){ alert(n); } return f2; } var result = f1(); result(); //999
闭包就是能够读取其他函数内部变量的函数
。
“定义在一个函数内部的函数”
。
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
闭包的作用就是在a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量
在上面的例子中,由于闭包的存在使得函数a返回后,a中的i始终存在,这样每次执行c(),i都是自加1后alert出i的值。
setTimeout和改写,为什么用,优点缺点
- setTimeout(code, millseconds) 用于延时执行参数指定的代码,如果在指定的延迟时间之前,你想取消这个执行,那么直接用clearTimeout(timeoutId)来清除任务,timeoutID 是 setTimeout 时返回的;
- setInterval(code, millseconds)用于每隔一段时间执行指定的代码,永无停歇,除非你反悔了,想清除它,可以使用clearInterval(intervalId),这样从调用 clearInterval 开始,就不会在有重复执行的任务,intervalId 是 setInterval 时返回的;
- requestAnimationFrame(code),一般用于动画,与 setTimeout 方法类似,区别是 setTimeout 是用户指定的(并且setTimeout挂起的程序是要等进程空闲的时候才执行,也就是时间不准),而 requestAnimationFrame 是浏览器刷新频率决定的,一般遵循 W3C 标准,它在浏览器每次刷新页面之前执行。
1.requestAnimationFrame可以代替setTimeout做动画(一般来说requestAnimationFrame频率为每秒60帧。-- 每帧16ms)
2.兼容性IE9-不支持
3.回退兼容的写法(不支持则使用setTimeout)
引申:跳帧的理解
浏览器绘制的帧速是60FPS,相当于16ms每一帧,如果使用setInterval的话,对于间隔时间到限制,以及对于每一次jsdom操作都是有限制的,因为网页这个渲染的线程是同步的,导致每一次对dom的操作 都涉及render layout painting 但是这个时间也许大于我们设置的间隔时间,导致在间隔时间内无法完成当前的绘制,造成丢帧,相反也会有浪费帧的现象。所以使用 requestAnimationFrame,这个是监听帧的完成,所以不会造成跳帧的现象。
-
继承 ---
- 借助构造函数
- 借助原型链
- 组合方式1
- 组合方式2
- 组合方式3
call,apply,bind的用法和区别
bind与apply、call最大的区别就是:bind不会立即调用(并且this将一直绑定在指定的作用域中,之后的每次调用都会使用这个作用域),其他两个会立即调用【apply接受的是数组参数,call接受的是连续参数】
使用区别:
都是用来改变函数的this对象的指向的;
第一个参数都是this要指向的对象;
都可以利用后续参数传参;
bind是返回对应函数,便于稍后调用,apply、call是立即调用;
function isArray(obj){
return Object.prototype.toString.call(obj) === '[object Array]' ;
}
- 作用域(ES5:全局作用域,函数作用域,ES6增加了块作用域)
- get和post请求,其他的请求方式PUT,DELET,HEAD等(get & POST的区别)
get 请求
post传输
put 修改
delete 删除
head 获取报文首部
以上建议看:高程 和 秘密花园http://bonsaiden.github.io/JavaScript-Garden/zh/
数组的常用方法
- 什么是类数组对象,如何将类数组对象转换成数组( Array.prototype.slice.call(), Array.from(), 扩展运算符[…] );
类数组对象:一个对象并不是由Array构造函数所创建的,它依然呈现出数组的行为(就是一个对象必须有length属性,没有length,Array.from() 转出来的就是空数组)
-
跨域问题和解决方法,jsonp实现
- JSONP 动态js 动态创建script标签异步加载完成的 callback = jsonp (告诉服务的函数名叫jsonp,同时在全局注册一个jsonp的函数,服务端返回其实就是运行了jsonp这个函数传的参数就是想要的数据)
- Hash
- postMessage
- webSocket
- CORS 跨域资源共享(cross-origin resource sharing)
-
原生ajax实现
var ajax = function(opt){ if (opt.url) { var xhr = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHttp'); var data = opt.data ,url = opt.url ,type = opt.type.toUpperCase(), ,dataArr = []; for(var k in data){ dataArr.push(k + '=' + data[k]) } if(type == 'GET'){ url = url + '?' + dataArr.join('&'); xhr.open(type, url.replace(/\?$/g,''),true); xhr.send(); } if(type == 'POST'){ xhr.open(type,url,true); xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded'); xhr.send( dataArr.join('&') ); } xhr.onload = function(){ if(xhr.status == 200 || xhr.status==304 || xhr==206){ var res; if(opt.success && opt.success instanceof Function){ res = xhr.responseText; if(typeof res === 'string'){ res = JSON.parse(res); opt.success.call(xhr,res); } } }else{ if (opt.error && opt.error instanceof Function) { opt.error.call(xhr, res); } } } }
}
事件委托(事件代理)
事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件xss漏洞和解决方法,了解CSRF漏洞
XSS又叫CSS(Cross site script 跨站脚本攻击)就是注入js脚本语句。程序对于用户输入内容未过滤,当用户浏览该页之时,嵌入其中Web里面的脚本代码会被执行,从而达到恶意攻击用户的特殊目的。
解决方法:不然js执行,过滤。表单提交或者url参数传递前,对需要的参数进行过滤
CSRF (ross-site request forgery)跨站请求伪造。
条件:1、接口有漏洞; 2、有登录信息
防御原理 :1)Token验证;2)Referer验证;3)隐藏令牌-
适配rem单位原理
rem单位元素的大小是根据html font-size基准变化- 通过dpr设置缩放比,实现布局视口大小,
- 动态计算html的font-size
banner轮播原理
还没看。。。。
css基础知识
-
盒模型
- 标准盒模型
- IE盒模型
清除浮动方法及原理
创建BFC(BFC是为了解决垂直边距折叠问题)
.clearfix:after {content:"."; display:block; height:0; visibility:hidden; clear:both; }
.clearfix { *zoom:1; } //为了适配ie6-
垂直居中(元素高度宽度不确定情况下的水平居中,垂直居中)
-
flex
#wrap{ display:flex; justify-content:center; align-items:center; }
给目标元素增加 1 个兄弟元素,或直接用父元素的 :before 或 :after,2 个元素均设置 display: inline-block、vertical-align: middle,兄弟元素设置 height: 100%;
表格布局:父元素设置 display: table-cell、vertical-align: middle;
CSS3:top: 50% 结合 transform: translateY(-50%)
-
- 几种布局
- 三栏布局( 两侧固定,中间自适应/中间固定,两侧自适应 )
- BFC,IFC
- 如何实现以下布局:
左侧200px,右侧自适应
如何实现一个footer总在底部,如果内容超过一屏,在内容底部,如果内容不够一屏,在屏幕底部
如果熟悉es6,可能会问一些es6的知识点:
http://es6.ruanyifeng.com/#docs/let
-
let
ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。for (let i = 0; i < 10; i++) { // ... } console.log(i); // ReferenceError: i is not defined
上面代码中,计数器i只在for循环体内有效,在循环体外引用就会报错。如果用var i的值为10
另外,for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
上面代码正确运行,输出了3次abc。这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。
与var的大致区别
1)不存在变量提升
- const 不可修改的变量声明(常量,但是什么的对象数组,表示地址不可以修改,内容可以更新)
-
箭头函数,和普通函数有什么区别(主要区别是this的指向)
-
普通函数中的this:
- this总是代表它的直接调用者, 例如 obj.func ,那么func中的this就是obj
2.在默认情况(非严格模式下,未使用 'use strict'),没找到直接调用者,则this指的是 window
3.在严格模式下,没有直接调用者的函数中的this是 undefined
4.使用call,apply,bind(ES5新增)绑定的,this指的是 绑定的对象
- this总是代表它的直接调用者, 例如 obj.func ,那么func中的this就是obj
箭头函数中的this
默认指向在定义它时,它所处的对象,而不是执行时的对象, 定义它的时候,可能环境是window(即继承父级的this);
-
promise 构造函数---new (resolve reject)处理异步请求回调
generator 方法声明是funciton 和函数名之间有个 * 里面yeild状态,一种状态机,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行
算法 【最后看】
冒泡排序,快速排序,二分查找,插入排序,合并排序
将一个[1,[2,3,[4]],[5],6]扁平化,变成[1,2,3,4,5,6]
var arr = [1,[2,3,[4]],[5],6]
-
基础递归
var resArr = [] function flatten(data){ if( Array.isArray(data) ){ data.forEach(function(item){ flatten(item) }) }else{ resArr.push(data) } } flatten(arr)
-
利用toString() + split(',') and map
arr.toString().split(',').map(item=>+item)
-
es6 Array.some
while( arr.some(item=>Array.isArray(item)) ){ arr = [].contat(...arr) }
框架(react,vue)
- 了解什么,具体了解哪些
- webpack和gulp等这些工具是否用过,有什么区别
读过哪些框架源码
zepto和jquery有什么区别
在用的框架例如hornbill,讲解下过程
业务
遇到过什么问题。如何解决的。一般说两三个。
性能优化
- 有哪些性能优化方法
- 缓存基础知识 强缓存&协商缓存
缓存相关的报文头cache-control, if-none-match, if-modified-since, Etag,expires, last-modified,cache-control last-modified if-none-match if-modified-since Etag expires - 浏览器的几种状态码 301和302什么区别
- 本地存储,几种存储方式的区别
sessionStorage
localStorage
databaseStorage
globalStorage - http相关知识:首部字段有哪些
点击ul中的li,弹出对应的序号
var ul = document.getElementById('ul');
var lis = ul.getElementsByTagName('li');
/* 利用index */
// for (var i = 0,len = lis.length; i < len; i++) {
// lis[i].index = i;
// lis[i].onclick = function(){
// console.log(this.index);
// }
// }
/* 利用闭包 - 立即执行函数 */
// for (let i = 0,len = lis.length; i < len; i++) {
// (function (idx){
// lis[idx].onclick = function(){
// console.log(idx);
// }
// })(i)
// }
// 利用事件委托
ul.onclick = function(ev){
var li = ev.target;
// console.log(li,li.nodeName)
if (li.nodeName.toLowerCase() === 'li') {
console.log( [...lis].indexOf(li) )
console.log( Array.from(lis).indexOf(li) )
console.log( Array.prototype.slice.call(lis).indexOf(li) )
console.log( [].indexOf.call(lis,li) )
}
}
话说小主开了一个微信公众号:[
民间程序员
],分享H5相关知识点,H5踩坑记,H5实战案例分享等,欢迎大家关注~