资讯专栏INFORMATION COLUMN

面试问题集锦

李文鹏 / 3192人阅读

摘要:创建对象工厂模式不能解决对象识别问题构造函数模式使用操作符。原型模式将构造函数模式里面的方法都包裹在一个对象里面,这样一方面实现了封装,另一方面解决了内存问题。

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 事件将不会被触发。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/111415.html

相关文章

  • web前端面试题一

    摘要:需求一个输入框,用户输入时有联想搜索,每次用户输入都会触发请求,过多的请求会造成服务器的压力,如何去解决这个问题请求函数面试者延迟发送可以去解决这样的问题。 写在前面的话 一般来说,面试质量的高低很大程度影响公司是否想接受改人才,也影响了人才是否愿意去公司。质量高的面试,公司能表明对人才的要求,个人也能表明所期待的公司是一个什么模式的公司。最终会有利于双向选择的过程。能尽早的把问题暴露...

    bergwhite 评论0 收藏0
  • 如何顺利通过编程面试

    摘要:事后看来,我认为它在我顺利通过微软的面试中发挥了重要作用。在过去几年中,技术公司正在转向使用在线协作编码平台进行远程面试。同样重要的是确保在整个面试过程中与面试官保持有效的沟通。 如果你是一个刚毕业的学生业生或一个职业生涯中期的工程师,那么准备接受你梦寐以求的工作的技术面试可能既费时又令人紧张。想象一下,人们期望你能够在现场解决一个复杂的挑战,并将其转化为无错误的代码? 好了,不用担心...

    _ivan 评论0 收藏0
  • 如何顺利通过编程面试

    摘要:事后看来,我认为它在我顺利通过微软的面试中发挥了重要作用。在过去几年中,技术公司正在转向使用在线协作编码平台进行远程面试。同样重要的是确保在整个面试过程中与面试官保持有效的沟通。 如果你是一个刚毕业的学生业生或一个职业生涯中期的工程师,那么准备接受你梦寐以求的工作的技术面试可能既费时又令人紧张。想象一下,人们期望你能够在现场解决一个复杂的挑战,并将其转化为无错误的代码? 好了,不用担心...

    fsmStudy 评论0 收藏0
  • 如何顺利通过编程面试

    摘要:事后看来,我认为它在我顺利通过微软的面试中发挥了重要作用。在过去几年中,技术公司正在转向使用在线协作编码平台进行远程面试。同样重要的是确保在整个面试过程中与面试官保持有效的沟通。 如果你是一个刚毕业的学生业生或一个职业生涯中期的工程师,那么准备接受你梦寐以求的工作的技术面试可能既费时又令人紧张。想象一下,人们期望你能够在现场解决一个复杂的挑战,并将其转化为无错误的代码? 好了,不用担心...

    jas0n 评论0 收藏0
  • 如何顺利通过编程面试

    摘要:事后看来,我认为它在我顺利通过微软的面试中发挥了重要作用。在过去几年中,技术公司正在转向使用在线协作编码平台进行远程面试。同样重要的是确保在整个面试过程中与面试官保持有效的沟通。 如果你是一个刚毕业的学生业生或一个职业生涯中期的工程师,那么准备接受你梦寐以求的工作的技术面试可能既费时又令人紧张。想象一下,人们期望你能够在现场解决一个复杂的挑战,并将其转化为无错误的代码? 好了,不用担心...

    Pikachu 评论0 收藏0
  • 技术面试老是有劲使不出,该怎么办?

    摘要:老王工作五六年了,今年刚从一家不小的公司出来,公司效益不好,年底裁员了,不幸老王在年前的最后一次裁员名单中中奖了。小黄心想,昨天复习了面试宝典里的数据库索引,老师说这个是要点,面试官怎么不按常理出牌呢。 又到了一年金三银四,回想到很多年前我刚参加工作时的面试经历,那时都是呆呆地等着面试官问问题,被问到一些自己并不熟悉的问题时要不就是思考半天也切不中要点,要不就只能无奈地回答并不清楚了。...

    史占广 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<