前端关于JavaScript的面试题(四)

46.知道不知道事件冒泡?知不知道阻止浏览器的默认行为?对应的原生兼容性写法该怎么写
事件冒泡:父元素和子元素上面的话都添加的有click(不仅仅是click事件,只要保证是同一个事件即可)。子元素的click事件触发的时候,会导致该click事件冒泡到它的父元素上面,为了阻止父元素的事件触发,我们一般需要给子元素的事件里写上阻止事件冒泡的方法

兼容性写法:
if(event.stopPropagation){
    event.stopPropagation();
}else if(event.cancelBubble){
    event.cancelBubble = true;
}

阻止浏览器默认行为:当我们不希望一些浏览器默认行为触发的时候,就需要给对应的事件添加上阻止浏览器默认行为。比如我们给a标签绑定click事件,当a标签的click事件触发之后,仍然会执行a标签自己的href

兼容性写法:
function cDefault(e){
    if(e.preventDefault){//ie9+
        e.preventDefault();
    }else{//ie 678
   		e.returnValue = false;
    }
}

47.什么是闭包(closure),为什么要用它?

闭包就是函数嵌套函数,并将该内部函数作为返回值返回或者存储在某个对象的属性里,这时就会形成一个闭包。

function aa(){
	var num = 10;
    return function bb(){
        console.log(num);
    }
}

var b = aa();
闭包的优点:
1.缓存,延长变量的作用域链
2.面向对象中的对象
3.实现封装,防止变量跑到外层作用域中,发生命名冲突

闭包的缺点:
1.闭包有一个非常严重的问题,那就是内存浪费问题,这个内存浪费不仅仅因为它常驻内存,更重要的是,对闭包的使用不当的话会造成无效内存的产生
2.性能问题 使用闭包时,会涉及到跨作用域访问,每次访问都会导致性能损失。
3.由于闭包内部变量优先级高于外部变量,所以多查找作用域链中的一个层次,就会在一定程度上影响查找速度。

48.知道原型和原型链么,一般什么时候需要用?

函数有一个prototype属性,叫原型属性。主要作用有两个:1.共享所有实例公共的属性和方法。2.继承

当我们有一个属性/方法需要被所有实例共享的时候,我们可以使用prototype

当我们需要实现js的继承关系的时候,我们可以使用prototype

原型链:

对象.__proto__ == 函数.prototyoe
函数.prototyoe.__proto__ == 父函数.prototype
父函数.prototype.__proto__ == 父父函数.prototype
...
父父父函数.prototype == Object.prototype
Object.prototype.__proto__ == null

这样就构成了原型链

49.有没有封装过插件,你一般怎么封装呢

封装过,我们主要用面向对象中的混合模式来封装插件,把可变的属性或者方法(通常都是属性)在构造函数内定义,把一些不变的属性或者方法(通常是方法)定义在函数的原型上面。我们封装好的插件通常会放在一个匿名自执行函数里面,这样做的目的是为了避免变量冲突。

50.Ajax和jsonp的原理?

Ajax的原理:Ajax基于浏览器内置的XMLHttpRequest对象与Web服务器端进行异步数据通信。
1.使用open方法与服务器建立连接
2.使用send方法向服务器发送数据
3.使用onreadystatechange来监听服务器响应的回调
4.使用responseText/responseXML获取服务器响应的数据

JSONP:是通过动态创建 script 标签向服务器发送请求获取响应的一种技术,在服务器需要返回一段JS脚本给客户端,客户端收到JS脚本立马执行对应的代码。为此,服务器应该设置响应头为 application/javascript

JSONP和Ajax没有任何关系。

51.你们移动端怎么开发的?用的什么单位、js库呢、怎么真机调试你们程序、怎么解决前缀问题呢

首先我们移动端用的是rem这个单位,移动端实际上还新增了vw,vh等一些单位,但是相对于rem来说,他们的兼容性都不好。rem是一个相对单位,是相对于根节点的font-size的比例。我们还会引用一个外部的js,这个js可以通过屏幕宽度动态计算根节点的font-size值。

我们移动端用的JS库是zepto.js,因为相应来说它的的体积的话要小很多。而且我们项目中有时会需要使用一些触屏事件,比如滑动事件,那么我们还会调用它里面的touch模块

我们webapp的话都是基于gulp搭建的前端工程来开发,因为利用gulp起一个webserver特别简单,并且我还可以实现livereload功能(当我监控的文件发生变化的时候,可以触发浏览器的自动刷新功能),而且在css3里面加前缀的话是一个很头疼的问题,我们现在只需要用autoprefixer模块就可以很容易实现自动加css3前缀这个功能了。

52.移动端兼容性?

bootstrap中起步中有:

1>ios移动端click事件300ms的延迟响应. 用fastclick来解决

2>zepto的touch模块的tap事件有点透的问题,也是用fastclick来解决

3>一些情况下对非可点击元素如(label,span)监听click事件,ios下不会触发,css增加cursor:pointer就搞定了

4>ios下取消input在输入的时候英文首字母的默认大写

<input autocapitalize="off"autocorrect="off" />

5>fixed定位缺陷

ios下fixed元素容易定位出错,软键盘弹出时,影响fixed元素定位
android下fixed表现要比iOS更好,软键盘弹出时,不会影响fixed元素定位
ios4下不支持position:fixed

解决方案: 可用iScroll插件解决这个问题

6>Input 的placeholder会出现文本位置偏上的情况

input 的placeholder会出现文本位置偏上的情况:PC端设置line-height等于height能够对齐,而移动端仍然是偏上,解决是设置line-height:normal

7>calc的兼容性处理

 CSS3中的calc变量在iOS6浏览器中必须加-webkit-前缀,目前的FF浏览器已经无需-moz-前缀。
 Android浏览器目前仍然不支持calc,所以要在之前增加一个保守尺寸:

div {
    width: 95%;
    width: -webkit-calc(100% - 50px);
    width: calc(100% - 50px);
}

8>在移动端修改难看的点击的高亮效果,iOS和安卓下都有效:

\ {-webkit-tap-highlight-color:rgba(0,0,0,0);}

9>阻止旋转屏幕时自动调整字体大小

html, body, form, fieldset, p, div, h1, h2, h3, h4, h5,h6 {-webkit-text-size-adjust:none;}

53.谈谈你对bootstrap的认识,用它做过项目么?

用Bootstrap主要用来做一些响应式的网站,它里面栅格化这块比较强大,我可以针对不同的屏幕尺寸定制不同页面结构。

我还用它做过后台管理系统,因为它里面集成的有风格标准统一的组件、插件、全局样式等,是我们做后台管理系统的话,不用再花大精力去布局页面了。而且甚至产品给我们一个原型图我们就可以开始开发,大大提高了开发效率。

54.javascript 继承的方法?
1.借助构造函数实现继承
    //  定义父类
    function Parent1 () {
        this.name = 'xxx',
        this.age = 18
    }
    //  定义子类
    function Child1 () {
        //通过call()方法改变Child1的this指向使子类的函数体内执行父级的构造函数从而实现继承效果
        Parent1.call(this)
        this.address = 'yyy'
    }
    //  构建子类的实例s1
    var s1 = new Child1()
    console.log(s1.name)  //xxx
	缺点:该方法的实力(s1)无法使用父类(Parent1)的原型(prototype)中的属性和方法
    
2.借助原型链实现继承
    function Parent2 () {
        this.name = 'xx',
        this.age = 19,
        this.play = [1,2,3]
    }
    //  一样在父类添加say方法
    Parent2.prototype = {
        say () {
            console.log('say')
        }
    }
    function Child2 (address) {
        this.address = 'yyy'
    }
    // 让子类的原型直接指向父类实例
    Child2.prototype = new Parent2()
    //  生成两个子类的实例s2、s3
    var s2 = new Child2()
    var s3 = new Child2()
    // s2实例继承了父类中的name属性
    console.log(s2.name)  //xx
    //  s2实例也同样继承了父类原型上的say方法
    console.log(s2.say())  //say
	缺点:在子类调用构造函数创建对象的时候,无法入参所有的属性值
    
3.组合继承
    function Parent5 () {
        this.name = 'xx',
        this.age = 20,
        this.play = [4,5,6]
    }
    function Child5 (name,age,address) {
        Parent5.call(this,name,age)
        this.address = address
    }
    // 比较关键的一步
    Child5.prototype = new Parent5()
    var c = new Child5("zhangsan",19,"无锡")

    
4.实例继承(为父类实例添加新特性,作为子类实例返回)
    function Animal (name) {
      // 属性
      this.name = name || 'Animal';
      // 实例方法
      this.sleep = function(){
        console.log(this.name + '正在睡觉!');
      }
    }
    // 原型方法
    Animal.prototype.eat = function(food) {
      console.log(this.name + '正在吃:' + food);
    };

    function Cat(){
      var instance = new Animal();
      instance.name = name || 'Tom';
      return instance;
    }
	// Test Code
    var cat = new Cat();
    console.log(cat.name);
    console.log(cat.sleep());
    console.log(cat instanceof Animal); // true
    console.log(cat instanceof Cat); // false

5.拷贝继承
    // 定义一个动物类
    function Animal (name) {
      // 属性
      this.name = name || 'Animal';
      // 实例方法
      this.sleep = function(){
        console.log(this.name + '正在睡觉!');
      }
    }
    // 原型方法
    Animal.prototype.eat = function(food) {
      console.log(this.name + '正在吃:' + food);
    };
    function Cat(name){
      var animal = new Animal();
     // 遍历拷贝属性
      for(var p in animal){
        Cat.prototype[p] = animal[p];
      }
      Cat.prototype.name = name || 'Tom';
    }

    // Test Code
    var cat = new Cat();
    console.log(cat.name);
    console.log(cat.sleep());
    console.log(cat instanceof Animal); // false
    console.log(cat instanceof Cat); // true
55.简述创建函数的几种方式
第一种(函数声明):
function sum1(num1,num2){
	return num1+num2;
}

第二种(函数表达式):
var sum2 = function(num1,num2){
	return num1+num2;
}

第三种(匿名函数):
function(){}:只能自己执行自己

第四种(new Function创建函数)
let str = 'return ' + '`Hello ${name}!`';
let func = new Function('name', str);
func('Jack') // "Hello Jack!"

56.把 Script 标签 放在页面的最底部的 body 封闭之前 和封闭之后有什么区别?浏览器会如何解析它们?

如果说放在 body 的封闭之前,将会阻塞其他资源的加载
如果放在 body 封闭之后,不会影响 body

57.js 延迟加载的方式有哪些?
  1. defer 和 async : js文件的加载不会堵塞页面的处理

    1. defer 属性
    <script src="file.js" defer></script> 
    defer属性声明这个脚本中将不会有 document.write 或 dom 修改。
    浏览器将会并行下载 file.js 和其它有 defer 属性的script,而不会阻塞页面后续处理。
     
    defer属性在IE 4.0中就实现了,超过13年了!Firefox 从 3.5 开始支持defer属性 。
    注:所有的defer 脚本保证是按顺序依次执行的。
    
    2. async 属性
    <script src="file.js" async></script> 
    async属性是HTML5新增的。作用和defer类似,但是它将在下载后尽快执行,不能保证脚本会按顺序执行。它们将在onload 事件之前完成。
    Firefox 3.6、Opera 10.5、IE 9 和 最新的Chrome 和 Safari 都支持 async 属性。可以同时使用 async 和 defer,这样IE 4之后的所有 IE 都支持异步加载。
    
    
  2. 动态创建 DOM 方式(创建 script,插入到 DOM 中,加载完毕后 callBack)

    var ga = document.createElement('script');
    ga.type = 'text/javascript';
    ga.async = true;
    ga.src = 'xxxx';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(ga, s);
    
    
  3. 由于JavaScript的动态性,还有很多异步加载方法: XHR Injection、 XHR Eval、 Script In Iframe

58.数组方法 pop() push() unshift() shift()各表示什么意思?
答:push()尾部添加、pop()尾部删除、Unshift()头部添加、shift()头部删除

59.Javascript 中 callee 和 caller 的作用?
caller 是返回一个对函数的引用,该函数调用了当前函数;
用法:fn.caller

callee 是返回正在被执行的 function 函数,也就是所指定的 function 对象的正文。
用法:arguments.callee

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值