雪碧图 http缓存 虚拟dom webpackjavascript
为何要三次握手? 三次握手: A:我能连你了吗? B: 能够连我,你连吧 A:那我连你了 开始发送数据css
缘由:由于要保证A/B 均可以收发信息 ,数据才能在AB之间传输html
A:我能连你了吗? B: 能够 说明A能够发信息,B能够接受信息html5
B: 能够连我,你连吧 A:那我连你了 说明B能够发送信息,A能够接受信息java
html5中新增长的标签,技术(api)(包括promise,localStorage,canvas等),统称为html5.webpack
.
类选择器,#
id选择器,input[type=text] [data-x] [target=_blank]
属性选择器web
直接子代选择器>
后代选择器空格 ,
表明两个都选面试
伪类选择器:
input:focus
选择得到焦点的 input 元素。 a:hover
p:first-child
p:last-child
p:nth-child(1)
p:nth-child(even)
p:nth-child(odd)
p:before
p:after
ajax
input:enabled
选择每一个启用的 元素。 input:disabled
选择每一个禁用的 元素 input:checked
选择每一个被选中的 元素。canvas
div{
border:1px solid red;
/*如下三行*/
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
复制代码
float
position:absolute
position:fixed
注意: position:relative
没有脱离文档流,只是相对于以前的位置定位,原来的地方还占据位置。position:absolute;top:0;bottom:0;left:0;right:0;margin:auto;
SVG:SVG实际上是一段代码,浏览器能够解析这段代码,将它变成图形 优势:能够渐变,不会失真,能够动
我理解flex从两个方面去理解:
/*容器上:*/
flex-direction/* 弹性元素按主轴排列的方向*/
flex-wrap/*nowrap | wrap | wrap-reverse,主轴排列不下,是否换行 。默认是nowrap不折行。不会溢出。元素的弹性伸缩*/
flex-flow/*上面两个的缩写*/
justify-content/* 主轴对齐方式,五个属性*/
align-items/* 单行交叉轴的元素对齐方式。默认stretch(元素未在交叉轴上设置尺寸,将把交叉轴自动填满,有flex-start,end,center,baseline几个属性)*/
align-content/*多行交叉轴的对齐方式。flex-wrap: wrap的时候。stretch(这几行在垂直方向上占满) | flex-start(这几行挤在上面) | flex-end(挤在下面) | center(挤在中间) | space-between | space-around */
/*元素上:*/
order/* 元素排列次序*/
align-self/* 单个元素的align-items*/
复制代码
flex-wrap: nowrap;
时,元素会伸缩。 在元素上写:flex-shrink
默认为1,按比例缩小,占满一行flex-grow:
放大比例。默认为0,不放大。若是两个子元素flex-grow:3,flex-grow:2,那么意思就是剩下的空间按3:2分配。flex-basis
默认为为auto
。若是有width
,就由width
决定,若是没有width
,就由内容的宽度决定。
flex-basis
有数值。忽略width
,由flex-basis
决定flex-basis:0
由内容宽度决定。由于他的优先级比width
高flex
是上面三个的缩写。
flex: 1 = flex: 1 1 0%
既之内容的大小(无论width是多少) 按比例放大或缩小,占满一行 -flex: auto = flex: 1 1 auto;
既考虑width, 按比例放大或缩小,占满一行flex: none = flex: 0 0 auto;
不放大也不缩小,width是多少,就是多少经常使用于固定尺寸 不伸缩width: calc(50% - 10px);
宽度100%会把父盒子撑破, 解决方法:
box-sizing:border-box;
width: calc(100% - 10px);
圣杯布局和双飞翼布局 是老的布局方式,2012年之前流行,如今已不流行,可是面试可能会考察到. why it?
原理:实际上都用了浮动和负边距的特性。 双飞翼实现方法: 1先所有fl 2main width100% 3 左边的一块 margin-left: -100%; /4/ 右边的一块 margin-left: -150px; /5/ 4.main.wrap{ margin-left: 100px; /6/ margin-right: 150px; /6/ background: blue; /7/ height: 350px; /7/ } 双飞翼:js.jirengu.com/fevifumike/…
内部元素彻底包起来(float等),外部元素界限分明,不重叠。
面试官问的时候就说:
@media (max-width: 768px){/*0-768*/
body{
background-color: blue;
}
}
@media (max-width: 425px){/*0-425*/
body{
background-color: red;
}
}
复制代码
2.加上meta viewport
历史缘由:最开始手机浏览器(苹果三)会在本身的三四百像素的手机上模拟980像素的显示效果,而后让用户本身去缩放,查看网页. 那么就告诉浏览器不要缩放网页,手机屏幕是多少像素,就显示多少像素的网页.使用下面的代码<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
复制代码
手机端什么CSS属性均可以用,不用考虑兼容的问题
动态 REM是手机专用,是如何适配全部手机的方案。 em
:一个m的宽度.若是面试官问,就说是一个汉字的宽度.这个单位是相对于font-size的 rem
:root em,根元素的font-size
.即 <html>
的font-size
.rem是相对于html的font-size的.
vh
:视口高度,总共100vh
vw
:视口宽度,总共100cw
pc端只须要选一个布局(flex或者float),而后定宽就能够了。可是手机端不行,由于屏幕太多了 解决方法:
动态rem: 由于rem
这个单位跟<html>
标签的font-size
挂钩。那么用js
将<html>
标签的font-size
与页面宽度挂钩(pagewidth),那么rem
这个单位就间接地与页面宽度挂钩了。
<head>
<meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <title>动态REM</title> <script></script> </head> 复制代码
而后布局等大单位就用rem,可是border,font-size等小单位,还用px便可,由于这些单位就算统一,在任何手机上的表现都没有多少影响。
这样写以后,10rem就是页面宽度。这样就能够总体按比例缩放了。
&&
,他的返回值就是遇到的第一个falsy值,后面的不看了 1&&2&&3&&0&&2&&3
返回0,后面的不运行。 ||
,他返回的就是第一个遇到的true值,后面的不看 0||0||0||false||1||2||0
返回1,后面的不运行。
七种数据类型分为六个基本类型和对象。 六个基本类型分别是null
,undefined
,string
,number
,boolean
,symbol
对象又分为object
,function
,array
相同点:if里都是都是false值
不一样点:
null
转换为数字的时候是0
, undefined
表示未定义转换为数字的时候是NaN
调用函数时,某个参数未设置任何值,这时就能够传入null
,表示该参数为空。而传入undefined
就表明undefined
yuchengkai.cn/docs/zh/fro… typeof只须要记住两点。
null
显示为 object
,其他均可以显示正确的类型function
都会显示object
Array.isArray(arr)
方法能够识别数组。除了下面六个值被转为false
,其余值都视为true
undefined
null
false
0
NaN
""或''(空字符串)
复制代码
NaN === NaN; // false
typeof NaN//number
复制代码
for in 遍历对象
for in循环注意点
for(var key in person){
console.log(person.key)
}
复制代码
注意:person.key
等于 person['key']
要用 这里遍历要用person[key]
for... in可能会随机遍历,不按照声明顺序
forEach遍历数组
var arr=[1,2,3]
arr.forEach(function(e){
console.log(e)
})
//1 2 3
复制代码
null
和undefined
没有tostring()
方法。只能null+''
和undefined+''
.toString()
方法。或直接+''
。或者window.String()
方法五个方法
'1234'-0
(经常使用)parseInt()
//默认十进制+'1'
取正记住5个false值 null undefined NaN 0 ''
记住下面易错点:
[]//ture
{}//ture
' '//ture 里面有空格
复制代码
转换方法两个:
window.Boolean(xxx)
!!xxx
引用: 一个广义对象(object,array,function) 例如 var a= {xxx:'xxx'} a存的是{xxx:'xxx'}这个广义对象的地址,假如是10000。那么a(或a存的地址10000)就是这个对象({xxx:'xxx'})的引用。
var a = 1 var b = a b = 2 请问 a 显示是几? 2 1 (深拷贝)
var a = {name: 'a'}
var b = a
b = {name: 'b'}
复制代码
请问如今 a.name 是多少? 'a'
var a = {name: 'a'}
var b = a
b.name = 'b'
复制代码
请问如今 a.name 是多少? 'b'
var a = {name: 'a'}
var b = a
b = null
复制代码
请问如今 a 是什么? {name: 'a'}
若是一个对象没有被引用,他就是垃圾,就会被回收(没有引用找不到他,因此要回收)
{name:'a'}
就是垃圾,就要被
回收,
释放内存
document.body.onclick
这个
引用在栈内存中存了fu这个函数的
地址
内存泄漏:在ie6的时候,若是关闭页面,一些垃圾是没有被清除,内存被永久的占用了
因此:
如何实现对象的浅与深拷贝?
Object.assign
来解决这个问题。let a = {
age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
复制代码
Object.assign()只拷贝第一层,若是属性存的是一个引用,那么他也只拷贝到引用。因此是浅拷贝JSON.parse(JSON.stringify(object))
来解决。let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE
复制代码
可是该方法也是有局限性的:
undefined
JavaScript有函数级做用域,仅仅函数能建立新做用域。
变量的做用域表示这个变量存在的上下文。
setTimeout中的函数所处在于全局做用域中,因此函数中使用this
关键字时,这个this
关键字指向的是全局对象(window
)
两个题目
var foo = 1;
function bar() {
if (!foo) {
var foo = 10;
}
alert(foo);
}
bar();
复制代码
答案是10
第二个例子
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
复制代码
alert输出了1
变量提高后的顺序 提高时代码表现上的排序为:
1 var a;
2 function f (){}
3 形参
4 this和arguments
复制代码
总结: var
声明变量,只会提高var a=undefined
(自动赋值为undefined
)。 function
声明函数,function f (){}
,全部的都会提高。
{ console.log(x) // Uncaught ReferenceError: x is not defined let x = 1 } let x = 1以前到花括号{,就是x的暂时死区,不用使用变量x,const同样
instanceof
运算符用来验证,一个对象是否为指定的构造函数的实例。obj instanceof Object
返回true
,就表示obj
对象是Object
的实例。
api太多
使用new命令时,它后面的函数依次执行下面的步骤。
既:
新对象.__proto__=构造函数.prototype
)this = 新对象
)第一步写私有属性,第二步写共有属性.
能够看到这个对象的
以现有的对象做为模板,生成新的实例对象,这时就可使用Object.create()
方法。
var person1 = {
name: '张三',
age: 38,
greeting: function() {
console.log('Hi! I\'m ' + this.name + '.');
}
};
var person2 = Object.create(person1);
person2.name // 张三
person2.greeting() // Hi! I'm 张三.
复制代码
this的实质:
this
就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。总结一句话:this就是指函数所在的当前环境(既所在的对象)
this:
this
表明新生成的实例对象this
就是属性或方法“当前”所在的对象。它老是返回一个对象。面试回答:;
fn()
里面的 this
就是 window
(fn在最顶层)fn()
是 strict mode
,this
就是 undefined
(fn在最顶层,严格模式下是undefined)a.b.c.fn()
里面的 this
就是 a.b.c
(属性或方法当前所在的对象。)new F()
里面的 this
就是新生成的实例() => console.log(this)
里面 this
跟外面的 this
的值如出一辙(ES6新增语法)(箭头函数里,this
就上一层的this
的值) 面试答上面的几个↑面试回答call() apply() bind(): 1 call()方法,能够指定函数内部this
的指向(即函数执行时所在的做用域),而后在所指定的做用域中,调用该函数。 (这个所指定的做用域意思就是所指定的对象)
var obj = {};
var f = function () {
return this;
};
f() === window // true
f.call(obj) === obj // true
复制代码
call
后面的参数则是函数调用时所需的参数
2 apply()
与call()
惟一的区别就是,它接收一个数组做为函数执行时的参数。
x.call(obj,1,2,3)
x.apply(obj,[1,2,3])
复制代码
3 bind方法用于将函数体内的this绑定到某个对象,而后返回一个新函数。 call
和apply
都是绑定新this
后直接执行函数,而bind
没有执行,而是返回新函数,这个在一函数做为参数的一些方法里就用bind
this面试题 带call的面试题遵循如下两个规则
若是call传了参数,this就是传的参数。
若是call没传参数或者为undefined,那么this是window(飞严格模式),或者undefined(严格模式)
带call的面试题仍然遵循规则 3.
记住了,当call()
的第一个参数是undefined
的时候, this
是 window
.
this面试题 this题目
答案: 调用B处的console.log().结果是options window(console.log()中console是全局window对象里的一个方法)
第二题:
答案:D Object
第三题:
答案:Object
举例
var a = [1,2,3]
a.push(4)
,push
是哪来的?a.__proto__ === Array.prototype
(a是实例数组对象,Array是构造函数)push
函数 就是沿着 a.__proto__
找到的,也就是 Array.prototype.push
Array.prototype
还有不少方法,如join
、pop
、slice
、splice
、concat
Array.prototype
就是 a 的原型(proto)聚完例子后用new对象举例,说给面试官听: 比若说
咱们新建立一个构造函数
function Person() {}
复制代码
而后根据构造函数构造一个新对象
var person1 = new Person();
``` 复制代码
每一个函数都有一个 prototype
属性,这个构造函数的 prototype 属性指向了一个对象,这个对象正是调用该构造函数而建立的实例的原型。
当咱们给Person
的prototype
的name
属性赋值为'Kevin'
Person.prototype.name = 'Kevin';
var person1 = new Person();
var person2 = new Person();
console.log(person1.name) // Kevin
console.log(person2.name) // Kevin
复制代码
每个新的实例对象对象都会从原型"继承"属性,实例对象拥有该原型的全部属性。
说白了,原型就是 构造函数 用来 构造 新实例 的 模板对象。
这就是原型。 开始解释原型链 那么咱们该怎么表示实例与实例原型,也就是 person1 和 Person.prototype 之间的关系呢,这时候咱们就要讲到第二个属性__proto__
。
先回答什么是原型。在上面,而后继续从__proto__
开始往下说。
说:
JavaScript对象除了 null 都具备的一个属性,叫__proto__
,这个属性会指向该对象的原型对象。
当读取实例的属性时,若是找不到,就会经过__proto__
查找原型中的属性,若是还查不到,就去找原型的原型。
例如Person.prototype
这个原型的原型就是Object
这个构造函数的prototype
,既Object.prototype
这个原型对象。而后,Person.prototype.__proto__
就指向Object.prototype
这个原型。而后Object.prototype
原型是null
。
这些原型对象经过__proto__
像链子同样连起来,就叫作原型链。 而后给面试官画:
链子上都画上__proto__
person1----->Person.prototype----->Object.prototype----->null
Array.prototype----->Object.prototype----->null
实例的.__proto__
指向构造函数. prototype
(原型对象) 面试题:
Number.prototype.__proto__ === Object.prototype
//true
String.prototype.__proto__ === Object.prototype
//true
Boolean.prototype.__proto__ === Object.prototype
//true
Array.prototype.__proto__ === Object.prototype
复制代码
//同理
Function.prototype.__proto__=== Object.prototype//true
复制代码
关于 Function只需记住下面: 构造函数的原型:
String.__proto__===Function.prototype//true
Number.__proto__===Function.prototype//true
Boolean.__proto__===Function.prototype//true
Object.__proto__ === Function.prototype//true
复制代码
特殊的:
Function.__proto__===Function.Prototype//true
复制代码
每个构造函数的prototype属性都指向原型对象。 每个原型对象的constructor属性都指向构造函数。 原型对象
console.log(Person === Person.prototype.constructor); // true
复制代码
大BUG:var a = Array(3)
一个参数,且参数为数字,那么久声明数组长度为3的空数组
var a = Array(3,3)
两个参数以上的时候,里面的参数都是数组内部的值。 因此声明数组不要用new Array()的方法。
数组本质上是一个对象。
数组能够用for i和for in循环
伪数组:
__proto__
指向Object.prototype
,没有pop
push
等方法length
arguments
,表明函数里面所传入的全部的参数。forEach
[1,2,3].forEach(function(value,index){
console.log(value)
console.log(index)
})
复制代码
sort&join&concat&map&filter&reduce segmentfault.com/a/119000001…
什么是DOM?
什么是DOM树?
Javascript操做DOM经常使用API总结http://luopq.com/2015/11/30/javascript-dom/
6Document.querySelectorAll()
函数声明的五种方式
注意其中一种方式:
1具名函数
function f(x,y){
return x+y
}
f.name // 'f'
2匿名函数
var f
f = function(x,y){
return x+y
}
f.name // 'f'
3具名函数赋值
var f
f = function f2(x,y){ return x+y }
f.name // 'f2'
console.log(f2) // undefined
4window.Function
var f = new Function('x','y','return x+y')
f.name // "anonymous"
5箭头函数
var f = (x,y) => {
return x+y
}
f.name//"f"
复制代码
只要记住三、4两种特殊的状况就好。
做用:建立一个独立的做用域,避免变量污染
(function(){alert('我是匿名函数')} ()) // 用括号把整个表达式包起来
(function(){alert('我是匿名函数')}) () //用括号把函数包起来
//下面的都是执行这个表达式,而无论返回值是什么
!function(){alert('我是匿名函数')}()
复制代码
另外一种建立独立做用域的方法是使用let
题目:
var a = 1
function f1(){
var a = 2
console.log(a)
f4()
}
function f4(){
console.log(a)
}
f1()
复制代码
答案,2,1 这个f4里面的a只能是他本身自己的做用域和他的父做用域,跟f1里面的a没有关系 先看面试题 题目1
var a = 1
function fn1(){
function fn2(){
console.log(a)
}
function fn3(){
var a = 4
fn2()
}
var a = 2
return fn3
}
var fn = fn1()
fn() //2
复制代码
题目2
var a = 1
function fn1(){
function fn3(){
var a = 4
fn2()
}
var a = 2
return fn3
}
function fn2(){
console.log(a)
}
var fn = fn1()
fn() //1
复制代码
题目3
var a = 1
function fn1(){
function fn3(){
function fn2(){
console.log(a)
}
var a
fn2()
a = 4
}
var a = 2
return fn3
}
var fn = fn1()
fn() //undefined
复制代码
解密
闭包经典面试题
经典面试题,循环中使用闭包解决 var 定义函数的问题
for ( var i=1; i<=5; i++) {
setTimeout( function timer() {
console.log( i );
}, i*1000 );
}
首先由于 setTimeout 是个异步函数,全部会先把循环所有执行完毕,这时候 i 就是 6 了,因此会输出一堆 6。
解决办法两种,第一种使用闭包(建立的这个当即执行函数就是一个新块级做用域,并使用了外部的变量i,解析完以后,也不随着i的最终改变而改变)+当即执行函数
for (var i = 1; i <= 5; i++) {
(function(j) {
setTimeout(function timer() {
console.log(j);
}, j * 1000);
})(i);
}
第三种就是使用 let 定义 i 了
for ( let i=1; i<=5; i++) {
setTimeout( function timer() {
console.log( i );
}, i*1000 );
}
由于对于 let 来讲,他会建立一个块级做用域,至关于刚才的闭包建立的块级做用域。
复制代码
用===
而不用==
。只须要注意两点
NaN ===NaN//false
===
也都是false
。由于地址不同。高级轮播 // 第一步,循环给按钮添加点击事件 //第二步:添加定时器,定时出发,循环轮播,而且进入时暂停轮播 jsbin.com/funumujoqe/…
无缝轮播 说思路就好了,而后说我在工做的时候都不手写录播,主要是为了理解他的原理,而后用别人写好的轮播库swiper,这样工做中的BUG会少一点。
callback 是一种特殊的函数,这个函数被做为参数传给另外一个函数去调用。这样的函数就是回调函数。 举一个Callback(回调函数)的例子 ,例如:
$button.on('click', function(){})
div.addEventListener('click', function(){})
复制代码
click 后面的 function 是一个回调,由于「我」没有调用过这个函数,是浏览器在用户点击 button 时调用的。
再举一个使用回调函数的例子
function setClock(callBack){
console.log('1定一个闹钟,三秒钟以后响');
setTimeout(()=>{
console.log('2三秒到了,闹钟响了!');
callBack();
},3000)
}
function getUp(){
console.log('3闹钟已经响了,该起床了')
}
setClock(getUp);
复制代码
回调函数通常只和**异步操做(setTimeOut)**在一块儿才使用!!!
JavaScript 只在一个线程上运行,JavaScript 同时只能执行一个任务,其余任务都必须在后面排队等待。
同步任务主线程上排队执行的任务。只有前一个任务执行完毕,才能执行后一个任务。
异步任务不进入主线程、而进入任务队列的任务。只有引擎认为某个异步任务能够执行了(好比 Ajax 操做从服务器获得告终果,或者setTimeOut到时间了(事件循环)),该任务(采用回调函数的形式)才会进入主线程执行
JavaScript 运行时,除了一个正在运行的主线程,引擎还提供一个任务队列(task queue),里面是各类须要当前程序处理的异步任务。
首先,主线程会去执行全部的同步任务。等到同步任务所有执行完,就会去看任务队列里面的异步任务。若是知足条件,那么异步任务就从新进入主线程开始执行,这时它就变成同步任务了。等到执行完,下一个异步任务再进入主线程开始执行。一旦任务队列清空,程序就结束执行。
异步任务的写法一般是回调函数。一旦异步任务从新进入主线程,就会执行对应的回调函数。若是一个异步任务没有回调函数,就不会进入任务队列,也就是说,不会从新进入主线程,由于没有用回调函数指定下一步的操做。
JavaScript 引擎怎么知道异步任务有没有结果,能不能进入主线程呢?答案就是引擎在不停地检查,一遍又一遍,只要同步任务执行完了,引擎就会去检查那些挂起来的异步任务,是否是能够进入主线程了。这种循环检查的机制,就叫作事件循环(Event Loop)。
问关于异步、主线程、事件循环(Event Loop)的时候:按照下面回答: 面试官问问题:js是单线程模式的,那么他是怎么实现异步操做的? 答:
异步操做的方法: 1.回调函数 2.事件监听(触发条件,执行回调函数) 3.ES6:Promise
它们向任务队列添加定时任务。时间到就添加,而后事件循环就会扫到,扫到了就执行里面的回调函数。
什么是Promise? 举例: $.ajax().then(成功函数,失败函数)
做用:避免回调嵌套,使回调变的可控
ES6划入标准标准。Promise如今是js的内置对象。Promise 对象是 JavaScript 的异步操做的解决方案。Promise 可让异步操做写起来,就像在写同步操做的流程,(链式使用,then以后能够继续then)而没必要一层层地嵌套回调函数
写一个Promise异步操做解决方案
function dosomething(){
// Promise 接受函数做为参数两个参数,
// resolve: 异步事件成功时调用
// reject: 异步事件失败时调用
return new Promise((resolve, reject) => {
let result = 异步操做()
// 下面给出承诺,面对不一样的结果,我会 执行 不一样的解决方案
if (result === 'success')
resolve('成功数据')
else
reject('失败数据')
})
}
// 异步操做,模拟几率事件
function 异步操做() {
return Math.random() > 0.5 ? 'success' : 'fail'
}
// 你在dosomething
dosomething()
// 异步操做成功了,那么咱们打印成功的数据
.then(res => console.log(res))
// 异步操做失败了,那么咱们打印失败的数据
.catch(res => console.log(res))
复制代码
Sync:同步的意思 Async:异步的意思
传统模块化方法:
//module1.js
!function(){
var person = window.person = {
name:"frank",
}
//局部变量person和全局变量person用的是同一个地址
}.call()
复制代码
虽然不一样变量,可是是一样的地址//module2.js
!function(){
var person = person;//即var person = window.person;
console.log(person);
}.call();
复制代码
//module1.js
!function(){
var person = {
name:"mataotao",
age:18,
};
window.mataotaoGrowUp = function(){
person.age+=1;
return person.age;
};
}.call();
复制代码
//module2.js
!function(){
var newAge = window.mataotaoGrowUp();
console.log(newAge);//19
}.call();
复制代码
用闭包的好处: