前端知识点总结

前端知识点总结

JavaScript

数组

ECMA数组大小可调整,当把一个值放在超出当前数组大小的位置上时,数组就会重新计算长度值,即长度值等于最后一项的索引加一,前面的值都自动被赋值为了undefined了。

同域

相同的域:域名,协议,端口都相同

if判断

if (obj) 等价于 if (toBoolean(obj)) 而不是If (obj != null )

JavaScript闭包

调用闭包函数访问外层变量,闭包外函数变量常住内存

闭包的作用

        function f1(){
        var n =1;

        return function(){
            alert(n)
        }; } 
var result = f1(); result();//1

1:读取函数内部的变量

就如上面闭包的例子,可以在函数外部读取函数内部的变量。

2:将变量的值始终保存在内存中

一般来讲,当函数执行完毕之后,函数内部的局部活动对象就会被销毁,内存中仅保存全局作用域,即js的内存回收机制。如果这个函数内部又嵌套了另一个函数,而这个函数是有可能在外部被调用到的.并且这个内部函数又使用了外部函数的某些变量的话.这种内存回收机制就会出现问题。如果在外部函数返回后,又直接调用了内部函数,那么内部函数就无法读取到他所需要的外部函数中变量的值了.所以js解释器在遇到函数定义的时候,会自动把函数和他可能使用的变量(包括本地变量和父级和祖先级函数的变量(自由变量))一起保存起来.也就是构建一个闭包,这些变量将不会被内存回收器所回收,只有当内部的函数不可能被调用以后(例如被删除了,或者没有了指针),才会销毁这个闭包,而没有任何一个闭包引用的变量才会被下一次内存回收启动时所回收。

坑:

function createFunction(){
    var result = new Array();
    for( var i = 0; i <10; i++){
        result[i] = function(){
            return i;
        };
    }
    return result;
}
var aa = createFunction();
alert(aa[0]());//10
alert(aa[1]());//10

在这个函数中,我们直接将闭包赋值给数组。这个函数会返回一个函数数组。表面上来看,似乎每个函数都应该返回自己的索引,即位置0的函数返回0,位置1的函数返回1一次类推。但实际上,如同上面例子,每个函数都返回了10。因为每个函数的作用域链中都保存createFunctions()函数的活动对象,所以它们引用的都是同一个变量i。当createFunctions()函数返回后,变量i的值死10,此时每个函数都引用着保存变量i的同一个变量对象。所以在每个函数内部i的值都是10。

所以,我们可以通过如下例子,创建一个自执行函数(匿名函数)强制让闭包的行为符合预期。

function createFunction1(){
     var result = new Array();
     for( var i = 0; i <10; i++){
         result[i] = function(num){
             return function(){
                 return num;
             };
         }(i);
     }
     return result;
 }

 var bb = createFunction1();
 alert(bb[0]());//0
 alert(bb[1]());//1

从createFunctions1()这个函数的执行结果来看,每个函数都返回各自不同的索引值了,是什么原因呢?
在createFunctions1()这个函数中,我们没有直接将闭包赋值给数组,而是定义了一个匿名函数,并将立即执行该匿名函数的结果赋值给数组。对于立即执行的匿名函数来说,由于外部无法引用它内部的变量,因此在执行完后很快就会被释放。所以这里的匿名函数有一个参数num,也就是最终的函数要返回的值。在调用每个匿名函数时,我们传入了变量i。由于函数是按值传递的,所以会将变量i的当前值赋值给参数num,而这个匿名函数内部,又创建并返回了一个返回num的闭包。这样一来,result数组中的每个函数都有自己num的一个副本,因此就可以返回各自不同的数值了。

传递赋值与引用赋值

var a = 30;
var b = a;
a = 20;
console.log( b )   // 30

var a = [1,2];
var b = a;
a[0] = 5;
console.log( b )  // [5,2]
  • number,string类型都是基本类型,而基本类型存放在栈区,访问时按值访问,赋值是按照普通方式赋值;

  • 对象和数组是通过引用来赋值的,所以改变a的同时b也会跟着改变。

undefined 与 null

  • alert(undefined==null) true

  • alert(undefined===null) false

  • alert(null==undefined) true

  • alert(null===undefined) false

undefined可以理解为从null中派生出的

var self = this

var self = this; self变量先保存外部函数指向的变量,当执行到函数内部this就会指向内部函数,可能会出现undefined,所以内部函数调用外部变量应该是用self。

var变量

  • 使用var声明变量,在方法内部是局部变量,在方法外部是全局变量
  • 没有使用var声明的变量,在方法内部或外部都是全局变量,但如果是在方法内部声明,在方法外部使用之前需要先调用包含变量的方法,告知系统声明了全局变量后方可在方法外部使用。

var、let、const

  • const定义的变量不可以修改,而且必须初始化。
  • var定义的变量可以修改,如果不初始化会输出undefined,不会报错。
  • let是块级作用域,函数内部使用let定义后,对函数外部无影响。
  • 变量提升:无论var变量在函数何处,执行时都会被提升到函数最上部(不会出现error,但是可能会出现undefined
  • let为块级作用域,使用{}划分,不能跨块访问

变量提升

console.log(a);//undefined

var a = "hey I am now hoisting";

相当于

var a;
console.log(a);//undefined

a = "hey I am now hoisting"

变量提升指的是变量声明的提升,不会提升变量的初始化和赋值。

Prototype

 var dom = function(){

};

dom.Show = function(){
    alert("Show Message");
};

dom.prototype.Display = function(){
    alert("Property Message");
};

dom.Display(); //error
dom.Show();  
var d = new dom();
d.Display();
d.Show(); //error
  1. 不使用prototype属性定义的对象方法,是静态方法,只能直接用类名进行调用!另外,此静态方法中无法使用this变量来调用对象其他的属性!   
  2. 使用prototype属性定义的对象方法,是非静态方法,只有在实例化后才能使用!其方法内部可以this来引用对象自身中的其他属性!

作用域

重中之重: 只有函数能创建作用域,其他的都不行

if(),for()等块语句,在块语句内部定义的变量会保留在它们已经存在的作用域内

var dom = function(){
    var Name = "Default";
    this.Sex = "Boy";
    this.success = function(){
        alert("Success");
    };
};

alert(dom.Name);
alert(dom.Sex);

两个都显示Undefined,为什么呢?这是由于在Javascript中每个function都会形成一个作用域,而这些变量声明在函数中,所以就处于这个函数的作用域中,外部是无法访问的。要想访问变量,就必须new一个实例出来。这里的this实际指向window

javascript除了全局作用域之外,只有函数可以创建的作用域。

作用域

作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。例如以上代码中,三个作用域下都声明了“a”这个变量,但是他们不会有冲突。各自的作用域下,用各自的“a”。

推荐博客

作用域链取值:

作用域链取值

要到创建这个函数的那个作用域中取值——是“创建”,而不是“调用”

作用域链查找过程:

第一步,现在当前作用域查找a,如果有则获取并结束。如果没有则继续;

第二步,如果当前作用域是全局作用域,则证明a未定义,结束;否则继续;

第三步,(不是全局作用域,那就是函数作用域)将创建该函数的作用域作为当前作用域;

第四步,跳转到第一步。

ES6特性

箭头函数特性:箭头函数的this其实就是在定义的时候就确定好的,以后不管怎么调用这个箭头函数,箭头函数的this始终为定义时的this

blog

object.call: 函数内部this指向了call或者apply指定的对象
call,bind,apply的使用

原型链及闭包理解
blog

this指向

  • 如果函数作为构造函数用,那么其中的this就代表它即将new出来的对象。平时为window对象
  • 如果函数作为对象的一个属性时,并且作为对象的一个属性被调用时,函数中的this指向该对象。如果函数被赋值到了另一个变量中(var f = var.fn();fn();),并没有作为obj的一个属性被调用,那么this的值就是window。
  • 函数作为对象属性内部定义函数中的this指向window

跨域方式

  • response.setHeader(“Access-Control-Allow-Origin”, “*”);
  • 使用标签进行跨域
  • jsonp方式不支持POST方式跨域请求,就算指定成POST方式,会自动转为GET方式;而后端如果设置成POST方式了,那就请求不了了。
  • 后端接口返回一个带有参数的方法名,其中函数的参数为返回信息,函数名为前端的回调函数名
  • jquery如果有success函数则默认success()作为回调函数。

HTML面试坑

浏览器端常用储存技术:

  • cookie
  • WebStorage(localStorage、sessionStorage)
  • UserData
  • IndexedDB

JavaScript内部对象

  • History 对象包含用户(在浏览器窗口中)访问过的 URL
  • Location 对象包含有关当前 URL 的信息
  • Window 对象表示浏览器中打开的窗口
  • Navigator 对象包含有关浏览器的信息

常用的页面的图片格式

有三种,GIF、JPG、PNG

cookie结束时间

如果不设置cookie结束时间,他会在关闭浏览器的时候销毁

不添加var的变量

  • 不添加var定义的变量相当于全局变量,无论是在函数内还是函数外。
  • 但是有这么个情况

    aa = 1;
    function test (aa){
      aa = 2;
        alert(aa) //输出2
    }
    test(aa)
    alert(aa)//输出1
    

看似在function中更改了全局变量2 应该输出2,2,但是function函数形参变量名仍为aa,所以相当于在函数体内隐式定义 var aa,所以函数体内aa相当于函数内局部变量,并没有修改全局aa

前端缓存机制

通过header中的cache-control字段来控制前端缓存机制

  • public 客户端与缓存代理服务器可以缓存
  • private 只能客户端进行缓存
  • expires 缓存过期时间
  • max-age 设定缓存过期时间(秒)可覆盖expires
  • no-cache 浏览器发送请求标识符到服务器做验证(协商缓存)
    • request携带if-modified-science 与 response中的last-modified进行对比,如果last-modified > if-modified-science,则从服务器返回资源,(status 200),否则使用硬盘缓存资源(status 304)
  • no-store 浏览器不进行缓存。

HTML+CSS

行内元素与块级元素

  • 行内元素有:a b span img input select strong
  • 块级元素有:div ul ol li dl dt dd h1 h2 h3 h4…p
  • 常见的空元素:

常用块级元素

常用块级元素

常用行级元素

常用行级元素

行级元素与块级元素区别

  • 块级元素会独占一行,其宽度自动填满其父元素宽度;
    行内元素不会独占一行,相邻的行内元素会排列在同一行,直至一行排不下才会换行,其宽度随元素的内容而变化。
  • 块级元素可以包含行内元素和块级元素;行内元素不能包含块级元素。
  • 行内元素设置width、height、margin-top、margin-bottom、padding-top、padding-bottom无效。

块级元素与行内元素的转换

  • display:inline-block;
  • display:inline;
  • display:block;

布局方式

常用5种布局方式
static | relative | absolute | sticky(不常用) | fixed

  • absolute:不为元素预留空间,通过指定元素相对于最近的非 static 定位(定义了position的父元素)祖先元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margins),且不会与其他边距合并。
  • static:该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时 top, right, bottom, left 和 z-index 属性无效。
  • relative:该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。position:relative 对 table-*-group, table-row, table-column, table-cell, table-caption 元素无效。
  • fixed:不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed 属性会创建新的层叠上下文。当元素祖先的 transform 属性非 none 时,容器由视口改为该祖先。
  • sticky :盒位置根据正常流计算(这称为正常流动中的位置),然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位。在所有情况下(即便被定位元素为 table 时),该元素定位均不对后续元素造成影响。当元素 B 被粘性定位时,后续元素的位置仍按照 B 未定位时的位置来确定。position: sticky 对 table 元素的效果与 position: relative 相同。

参考

box-sizing

当你设置了元素的宽度,实际展现的元素却超出你的设置:这是因为元素的边框和内边距会撑开元素。
当你设置一个元素为 box-sizing: border-box; 时,此元素的内边距和边框不再会增加它的宽度。

清除浮动

  1. 使用 clear 指定对应元素左侧或者右侧没有浮动元素
  2. 使用overflow关键字

百分比

百分比是一种相对于包含块的计量单位。对应父级元素的宽或高。

响应式布局

媒体查询是做此事所需的最强大的工具。使用百分比宽度来布局,然后在浏览器变窄到无法容纳侧边栏中的菜单时,把布局显示成一列:

@media screen and (min-width:600px) {
  nav {
    float: left;
    width: 25%;
  }
  section {
    margin-left: 25%;
  }
}
@media screen and (max-width:599px) {
  nav li {
    display: inline;
  }
}

inline-block

inline-box可以使元素达到横向浮动的效果,并且不需要让后续或者前面的元素清除浮动

  • vertical-align 属性会影响到 inline-block 元素,你可能会把它的值设置为 top 。
  • 你需要设置每一列的宽度
  • 如果HTML源代码中元素之间有空格,那么列与列之间会产生空隙

flexbox布局

新的布局标准,可能有些不规范与低兼容性

Flex 是 Flexible Box 的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。

display: flex //块级元素
display: inline-flex //行内元素
display: -webkit-flex; /* Safari */
  display: flex

设为 Flex 布局以后,子元素的float、clear和vertical-align属性将失效。

采用 Flex 布局的元素,称为 Flex 容器(flex container),简称”容器”。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称”项目”。

容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end。

项目默认沿主轴排列。单个项目占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size。

flexbox布局常用属性

  • flex-direction
    • lex-direction属性决定主轴的方向(即项目的排列方向)
    • flex-direction: row | row-reverse | column | column-reverse;
  • flex-wrap
    • 默认情况下,项目都排在一条线(又称”轴线”)上。flex-wrap属性定义,如果一条轴线排不下,如何换行。
    • flex-wrap: nowrap | wrap | wrap-reverse
  • flex-flow
    • flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。
    • flex-flow: || ;
  • justify-content
    • justify-content属性定义了项目在主轴上的对齐方式。
    • justify-content: flex-start | flex-end | center | space-between | space-around;
  • align-items
    • align-items属性定义项目在交叉轴上如何对齐。
    • align-items: flex-start | flex-end | center | baseline | stretch;
  • align-content
    • align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
    • align-content: flex-start | flex-end | center | space-between | space-around | stretch;

flex布局的item属性

  • order
    • order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
  • flex-grow
    • flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
    • 如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
  • flex-shrink
    • flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
    • 如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。负值对该属性无效。
    • flex-shrink: ; / default 1 /
  • flex-basis
    • flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
    • 它可以设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。
    • flex-basis: | auto; / default auto /
  • flex
    • flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
    • 该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。
    • 建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
    • flex: none | [ <’flex-grow’> <’flex-shrink’>? || <’flex-basis’> ]
  • align-self
    • align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
    • align-self: auto | flex-start | flex-end | center | baseline | stretch;

水平居中

  1. 行内元素: 要实现行内元素的水平居中,只需把行内元素包裹在块级父层元素中,并且在父层元素CSS设置text-align:center
  2. 块级元素: 要实现块状元素(display:block)的水平居中,我们只需要将它的左右外边距margin-left和margin-right设置为auto,即可实现块状元素的居中(需要设置宽度)
  3. 多个块状元素的水平居中:
  4. 要实现多个水平排列的块状元素的水平居中,传统的方法是将要水平排列的块状元素设为display:inline-block,然后在父级元素上设置text-align:center
  5. 使用flexbox实现多个块状元素的水平居中:
    1. 原理: flexbox由伸缩容器和伸缩项目组成。通过设置元素的display属性为flex或者inline-flex可以得到一个伸缩容器。设置为flex的容器被渲染为一个块级元素,而设置为inline-flex的容器则渲染为一个行内元素。而每一个被设置为flex的容器,它的内部元素都将变成一个flex项目,即是一个伸缩项目。简单的说,flex 定义了伸缩容器内伸缩项目该如何布局。
    2. 父级元素#container{justify-content:center;display:flex;}

垂直居中

已知高度宽度元素的水平垂直居中

1.绝对定位与负边距实现:

利用绝对定位,将元素的top和left属性都设为50%,再利用margin边距,将元素回拉它本身高宽的一半,实现垂直居中。核心CSS代码如下:

#container{
position:relative;
}

#center{
width:100px;
height:100px;
position:absolute;
top:50%;
left:50%;
margin:-50px 0 0 -50px;
}

2.绝对定位与margin

这种方法也是利用绝对定位与margin,但是无需知道被垂直居中元素的高和宽。核心代码如下:

#container{
position:relative;
}

#center{
position:absolute;
margin:auto;
top:0;
bottom:0;
left:0;
right:0;
}

未知高度和宽度元素的水平垂直居中

1.当要被居中的元素是inline或者inline-block元素

当要被居中的元素是inline或者inline-block的时候,可以巧妙的将父级容器设置为display:table-cell,配合text-align:center和vertical-align:middle即可以实现水平垂直居中。

#container{
display:table-cell;
text-align:center;
vertical-align:middle;
}

#center{

}

2.CSS3

利用CSS3的transform,可以轻松的在未知元素的高宽的情况下实现元素的垂直居中。

#container{
position:relative;
}

#center{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

3.flex布局

使用flex布局,无需绝对定位等改变布局的操作,可以轻松实现元素的水平垂直居中。

#container{
display:flex;
justify-content:center;
align-items: center;
}

#center{

}