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
识别类。而且此时constructor
是enumerable
,因此最好使用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
第三个参数为false
,send
会阻塞,这时可以直接通过status
和responsText
检查。默认为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 事件将不会被触发。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。