1.每个东西的出现都有它要解决的问题:可从创建对象说。

1. CSS盒子模型:

box-sizing:content-box | border-box

- `content-box`:默认值,width指内容宽度。
- `border-box`:width = border+padding+内容宽度(IE怪异模式)

2. 居中


vertical-align只针对内联元素。默认值baseline只内联元素的底部与文字底部在一条直线上。还取值middle,text-bottom,text-top,sub,super,top,bottom。(看这篇文章

middle : Aligns the middle of the element with the middle of lowercase letters in the parent.

tabel-cell默认设置了vertical-align:middle

答题思路:

1) 分为水平、垂直、水平垂直;各方面又分为内联元素和块级元素;

2)水平内联:text-align;水平块级:margin,flex,inline-block

3) 垂直内联:a.一行:padding,line-height;b.多行:padding,tabel-cell,vertical-align,flex,column。
垂直块级:position,transform,flex

4)水平垂直:a.position,transformXY;b.flex

3. position

  • static:默认值。正常文档流。

  • relative:相对本身位置。正常文档流。

  • absolute:相对值不是static的祖先元素定位。脱离文档流。

  • fixed:相对于屏幕视窗的位置来指定元素的空间,定住不动。脱离文档流。

4.BFC

触发BFC的条件:

  • float的属性不是none;

  • overflow的属性不是visible;

  • position的属性是absolute,fixed;

  • display的属性是:inline-block,table-cells,table-caption.

BFC的布局特性:

  • 内部盒子在垂直方向一个接一个放置。

  • 兄弟元素的外边距由margin决定,在同一个BFC里的垂直边距会叠加。(解决办法:创建一个新的BFC)

  • BFC的高度包含浮动元素。(可用以消除浮动)

  • BFC的区域不会与浮动盒子重叠。(解决图片环绕效果)

  • BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。

5.创建对象

  • 工厂模式:不能解决对象识别问题.

function createPerson(name){
    var o = new Object()
    o.name = name
    o.sayName = function(){
        alert(this.name)
    }
    return o
}
  • 构造函数模式:使用new操作符。用constructor属性解决对象识别问题。

    
    过程:创建新对象 => this绑定到新对象 => 执行函数中的代码 => 返回新对象。
    
    缺点:每一个`sayName`方法都是一个函数实例,即每一个对象都有一个该实例,则多个对象多个该函数实例实现相同效果,浪费内存。
    
    解决方法:将`sayName`作为一个全局函数,则都指向该实例。但是该函数就暴露在全局,不存在封装性。
    
function Person(name){
    this.name = name
    this.sayName = function(){
        alert(this.name)
    }
}
  • 原型模式:将构造函数模式里面的方法都包裹在一个对象里面,这样一方面实现了封装,另一方面解决了内存问题。这个对象就称为原型对象。

    1)构造函数通过prototype访问这个原型对象,赋给构造函数,是因为在没有实例化的时候就根本访问不到原型对象了,不能给原型对象赋值,所以要把这个原型对象给构造函数。
    2)每创建一个函数,就会同时创建prototype对象,并且有初始值constructor属性,指向构造函数。同时这个属性是所有实例都应该有的,因此放到原型对象上;

    例如,当你这样: var a1 = new A(), JavaScript 就会设置:a1.[[Prototype]] = A.prototype(在内存中创建对象后,并在运行 this 绑定的函数 A()之前)

    3)实例通过__proto__属性访问原型对象。

    综上,实例与构造函数并无直接关系,原型对象和二者皆有关。

    缺点:1)所有实例都有相同的属性,比如name;

      2)对于引用型对象来说,一个实例改变了该值,则其他实例的该值也会改变。
    
    function Person(){
    }
    
    Person.prototype.name = nina
    Person.prototype.sayName = function(){
        alert(this.name)
    }

    注意:若用Person.prototype = {}写原型时,要明确声明constructor:Person,否则默认为Object。但是此时仍能用instanceof识别类。而且此时constructorenumerable,因此最好使用defineProperty设置constructor.

  • 组合构造函数和原型模式:构造函数传递自由属性,原型设置共享属性和方法。

  • 动态原型模式:检验某种属性是否存在,若不存在则在原型中创建它。只在首次实例化时有效,因为之后该属性就已经在原型上了。【并没有想到它的应用场景】

    function Person(name){
        this.name = name
        if(typeof this.sayName != 'function'){
            Person.prototype.sayName = function(){
                alert(this.name)
            }
        }
    }
  • 寄生构造函数模式:工厂模式+new。这样返回的是工厂函数中的对象,它与构造函数、原型对象没有任何关系,同时不能依赖instanceof识别。主要用于给Array等内置对象新增方法而不修改Array的原型。

    function specialArray(){
        var value = new Array()
        values.push.apply(values,arguments)
        values.toPipedString = function(){
            return this.join('|')
        }
        return values
    }
    
    var color = new specialArray('red','blue','green')
    color.toPipedString() // 'red|blue|green'
  • 稳妥构造函数:在不能使用this,new的安全环境下使用。

    function Person(name){
        var o = new Object()
        o.sayName = function () {
            alert(name)
        }
        return o
    }

6. 继承

  • 原型链:基于原型和原型搜索机制。基本思想为:a的原型设置为另一个对象的实例b,那么b的__proto__指向b的原型。则a通过原型搜索机制能够访问b和b的原型的属性和方法,实现了继承。如果b的原型为实例c,那么a就继承了b,c。至于为什么不让a的原型等于b的原型而是实例b呢,这样就同时也继承了b的属性。否则的话a和b其实并没有区别。最终的原型还是Object.prototype

每个对象都有一个指向它的原型(prototype)对象的内部链接。这个原型对象又有自己的原型,直到某个对象的原型为 null 为止(也就是不再有原型指向),组成这条链的最后一环。这种一级一级的链结构就称为原型链(prototype chain)。

function Super(){
    this.proerty = true
}
Super.prototype.getSuperValue = function () {
    return this.property
}
function Sub(){
    this.subproperty = false
}
Sub.prototype = new Super()
Sub.prototype.getSubValue = function () {
    return this.subproperty
}
var instance = new Sub()
instance.getSuperValue() //true

缺点:1)超类构造函数的属性中存在引用类型,这时子类若修改该属性则其他实例也会受影响。相当于这时的实例就是前面提到的原型对象。
2)子类不能给超类的构造函数传递参数。

  • 借用构造函数:在子类构造函数中调用父类的构造函数。解决引用类型值和给父类构造函数传参数。

function Super(name) {
    this.colors = ['red','blue']
    this.name = name
}

function Sub() {
    Super.call(this,'nina')//相当于前面创建对象原型模式的解决方案
    this.age = 29
}

缺点:1)子类无法调用父类原型的方法;2)多个方法占用空间的问题;

  • 组合继承:在子类构造函数中调用父类构造函数传递参数,子类原型为父类实例。

function Super(name) {
    this.colors = ['red','blue']
    this.name = name
}

Super.prototype.sayName = function () {
    alert(this.name)
}

function Sub(name,age) {
    Super.call(this,name)  //第二次调用
    this.age = age
}

Sub.prototype = new Super()  //第一次调用
//这个时候是将父类的构造函数在子类中调用,因此构造函数为子类,父类的构造函数在子类中就不在了
Sub.prototype.constructor = SubType
Sub.prototype.sayAge = function () {
    alert(this.age)
}

缺点:调用两次构造函数。因此父类实例的属性在子类实例和原型中都有一份,存在两份。

  • 原型式继承:Object.create(obj,property)。在没有必要创建构造函数,而只是想让一个对象与另一个对象相似的情况下使用。这样不用调用构造函数,否则让obj成为原型则必须要构造函数。

  • 寄生组合式继承:组合继承调用了两次父类的构造函数。结合Object.create

function Super(name) {
    this.colors = ['red','blue']
    this.name = name
}

Super.prototype.sayName = function () {
    alert(this.name)
}

function Sub(name,age) {
    Super.call(this,name)  //第二次调用
    this.age = age
}

var prototype = Object.create(Super.prototype) //减少之前的这一步的构造函数的调用
prototype.constructor = Sub
Sub.prototype = prototype

7. 按需加载Ajax

  • 指定请求的过程:

    • var xhr = new XMLHttpRequest()

    • xhr.open(请求方法:post副作用、get,url)

    • xhr.setRequestHeader()设置请求头,可选

    • xhr.send(null/data)指定请求主体并发送。一般get没有参数或者是null,post将传输的数据作为参数。

  • 响应返回值:

    • status/statusText:返回HTTP状态码。200成功。

    • getResponseHeader/getAllResponseHeaders:查询响应头。

    • responseText文本形式/responseXML文档形式返回相应主体。

  • readystatechange:监听该事件才能获得响应返回值。

    • 0 unsent open()尚未调用

    • 1 opend open()已调用

    • 2 headers_received 接收到头信息

    • 3 loading 接收到响应主体

    • 4 done 相应完成

    var request = new XMLHttpRequest()
    request.open('get',url)
    request.onreadystatechange = function(){
        if(request.readyState === 4 && request.status === 200){
            var type = request.getResponHeader('Content-Type')
            if(type.match(/^text/){
                callback(request.responsText)
            }
        }
    }
    request.send(null)
  • 同步调用:
    open第三个参数为falsesend会阻塞,这时可以直接通过statusresponsText检查。默认为true,异步调用。

  • 请求主体编码:

    • 表单:name=value&name=value数组,join(&)

    • json:JSON.stringify

  • progress事件、load、error、abort

request.onprogress = function (e) {
    //lengthComputabel告诉是否知道内容长度,知道则为true
    if(e.lengthComputable){
        //loaded目前传输的字节数,total数据传输的总长度
        progress.innerHTML = Math.round(100*e.loaded/e.total) + "% Complete"
    }
}
  • abort()完成取消或超时请求小号的时间太长或当响应变得无关时。timeout属性指定请求自动中止后的毫秒数。

  • 杂项

    • 你需要在请求调用 open() 之前添加事件监听。否则 progress 事件将不会被触发。


Yawenina
2.3k 声望117 粉丝