前端面试

面试

1.实现一个函数,判断其是不是会文字符串

function run(input){
 if(typeof input !=="string") return false
 return input.split("").reverse().join("")==input   
}

2.用两种以上方式实现垂直水平居中

.wrapper{
    position:relative;
    .box{
        position:absolute;
        top:50%;
        left:50%;
        transform:translate(-50%,-50%);
    }
}
​
.wrapper{
    .box{
        disaplay:flex;
        justify-content:center;
        align-itemscenter;
        height:100px;
    }
}
​
.wapper{
    display:table;
    .box{
        display:table-cell;
        vertical-align:middle;
    }
}

3.实现一个点击父元素的区域不包含子区域事件效果

<ul id="ul" style="height:200px;">
        <li id="li" style="height:100px;background-color: aquamarine;"></li>
    </ul>
  
</body>
<script>
    var ul = document.getElementById("ul")
    var li = document.getElementById("li")
    ul.onclick = function (e) {
        e = e || window.event
        if (e.target.tagName.toLowerCase() != "li") {
            li.style.background = "yellow"
            console.log(1);
​
        }
    }
</script>

4.请你简单的实现一个双向绑定

<input id="input" />
    <script>
        const data = {};
        const input = document.getElementById('input');
        Object.defineProperty(data, 'text', {
            set(value) {
                input.value = value;
                this.value = value;
                console.log(this);
​
            }
        });
        input.onchange = function (e) {
            data.text = e.target.value;
        }
    </script>

5.实现Storage,使得该对象为单例,并对localStorage进行封装设置值setItem(key,value)和getItem(key)

var instance = null;
class Storage {
  static getInstance() {
    if (!instance) {
      instance = new Storage();
    }
    return instance;
  }
  setItem = (key, value) => localStorage.setItem(key, value),
  getItem = key => localStorage.getItem(key)
}
​

ps:类(class)通过static 关键字定义静态方法,不能再类的实例上调用静态方法,而应通过类本身调用

lass ClassWithStaticMethod {
  static staticMethod() {
    return 'static method has been called.';
  }
}
​
console.log(ClassWithStaticMethod.staticMethod());
// expected output: "static method has been called."

6.form中的input可以设置readyonly和disable,请问二者有什么区别

readyonly不可编辑,但可以选择复制,只可以传递到后台,disabled不能编辑,不能选择,不能复制,之不可传到后台

7.清楚浮动的几种方法

  • 给父元素定义高度

  • 给父级元素添加overflow:hidden;

  • 给浮动元素最后添加一个空的块级元素,并给该块级元素添加{clear:both}

  • 给父级元素添加伪元素

.clearfix:after{
    content:".";
    diaplay:block;
    height:0;
    visibility:hidden;
    clear:both;
}

8.src 与href的区别

1.src指向外部资源的位置,指向的内容将会被嵌入到文档中当前标签所在的位置,在请求src资源时会将其指向资源下载并应用到文档中

2.href建立文档链接

9.阐释下面代码执行结果

<script>
    if (a in window) {
        var a = 'hello js';
    }
    console.log(a)
</script>

解:if并不是一个代码块

1.进行预解析代码,观察到有一个变量声明

2.预解析结束开始执行代码

3.log=>hello.js

console.log( func );
var func = 123;
console.log( func );
function func() {
  console.log( 'Hello js' );
}

解:

变量和函数同时变量同时提升,函数声明是后来上的覆盖了前面的变量提升所以第一个func打印出来的是函数体//

开行运行,之后123又赋值给func所以第二个func打印的是123

ps:先执行变量提升,后面的覆盖前面的,然后一句一句执行

10.比较下面两个代码

function func1 ( num ) {
  console.log( num );
  var num = 456;
  console.log( num );
}
var num = 123;
func1( num );

//分析
//1. 进行预解析,观察声明有两个,一个函数声明func1,一个是变量声明var num
//    func1被预解析记录,并与函数体相连
//    var num 被记录
//2. 预解析结束,开始执行代码
//    执行第一句话为:num = 123,对num进行赋值
//    调用func1( num );
//    在进入函数体前,开辟函数内存需要的内存空间,将函数的参数var num = 123进行声明
//    进入函数体,开始执行预解析,观察到有个var num,重复声明,忽略
//    执行函数体,第一个console.log( num ) => 123
//    num = 456,对num进行赋值
//    第二个console.log( num ) => 456
//    函数执行结束,回到外层
function func2 () {
  console.log( num );
  var num = 456;
  console.log( num );
}
var num = 123;
func2( num );

//分析
//1. 进行预解析, 观察到有两个声明, func2和var num
//   func2被记录,并与函数体相连
//   var num被记录
//2. 预解析结束,开始执行代码
//    执行num = 123,对num进行赋值
//    调用func( num )
//    进入函数体,进行预解析, 记录var num
//    执行第一个console.log( num ) => undefined
//    执行赋值语句, num = 456
//    执行第二个console.log( num ) => 456

解:同样是两个代码但是一个要求传入形参,一个不要形参为什么差别这么大?其原因在于,形参相当于在函数体中直接使用这个,然后直接套用就好,但是函数内部也有一个预解析()所以会发生变量提升,并且,函数内部的变量一旦发现自己有,就不会向上级索要(闭包)

function func3 () {
  console.log( num );
  num = 456;
  console.log( num );
}
var num = 123;
func3( num );
console.log( num );

//分析
//1. 进行预解析, 观察到有两个声明,func3和var num
//    func3被记录,并与函数体相连
//    var num被记录
//2. 预解析借宿,开始执行代码
//   num = 123,进行赋值
//   调用func3( num )
//    进入函数体,进行预解析,无需要记录对象,预解析结束
//    执行第一个console.log( num ) => 此时函数的局部作用域内无num,向全局中找,全局num = 123 => 123
//    num = 456,进行赋值操作 => 更改全局中的num = 456
//    执行第二个console.log( num ) => 456
//    函数执行完毕,执行第三个console.log( num ) => 456
var num = 123;
function f1 () {
  console.log( num );  
}
function f2 () {
  var num = 456;
  f1();
}
f2();
console.log( num );

//分析
//1. 进行预解析,观察到有3个声明,两个函数声明,一个变量声明
//   var num被记录
//   f1被记录,并与函数体相连
//   f2被记录,并与函数体相连
//2. 预解析结束,开始执行代码
//    num = 123,进行赋值
//    调用f2();
//    进入f2函数体内,进行预解析, var num被记录
//    进行赋值操作 num = 456
//    调用f1()
//    进入f1函数体内,进行预解析,无需要记录对象,预解析结束
//    执行第一个console.log( num ) => 函数体内无num, 向全局作用查找, 全局num = 123 => 123
//    函数执行完毕
//    执行第二个console.log( num ) => 123

解:服了,在函数体中var声明是一个局部变量,不声明反而是一个全局变量

f2();
var num = 123;
function f1 () {
  console.log( num );  
}
function f2 () {
  var num = 456;
  f1();
}
console.log( num );
//1. 进行预解析,观察到有3个声明,两个函数声明,一个变量声明
//   var num被记录
//   f1被记录,并与函数体相连
//   f2被记录,并与函数体相连
//2. 预解析结束,开始执行代码
//   调用f2()
//   进入f2函数体内,进行预解析, var num被记录
//   进行赋值num = 456
//   调用f1()
//   进入f1函数体内,执行第一个console.log( num ) =>函数体内无num,向全局作用域查找,此时num = undefined => undefined
//   函数执行完毕
//   num = 123,进行赋值
//   执行第二个console.log( num ) => num = 123

11.驼峰命名规则

将骆驼命名规则的字符串转换成使用短横线命名法的字符串, 并且全小写 .例如: 'getElementById' => 'get-element-by-id'

function getKebabCase ( str ) {
 var arr = str.split('');
    str = arr.map(function ( item ){
        if( item.toUpperCase() === item ){
            return '-' + item.toLowerCase();
        }else{
            return item;
        }
    }).join( '' );
    return str;
}
console.log( getKebabCase( 'getElementById' ) ); //get-element-by-id

12.哪些操作会造成内存泄露

内存泄露是指向系统申请了内存后不能释放,使得这片内存不能再被重新申请,以下的操作会造成内存泄露

1.当页面中的元素被移除或替换时,若元素绑定的事件没有被移除,在ie中不会做出处理,此时要手工移除事件,不然会造成内存泄露

2.在IE中,如果循环引用的对象是dom节点,会造成内存泄露

3.闭包时构成循环引用会造成内存泄露

3.在ie中,自动类型转换会造成内存泄露

13.chrome 浏览器中文界面下默认会将小于12px的文本强制按照12px显示,可以通过加入css样式

-webkit-text-size-adjust: none; 解决。

14.盒模型

.IE盒模型:margin content (包含border,padding)

.w3c盒模型:margin,border,padding,content

css3中的box-sizing 属性就是这两种模式,border-box(ie);content-box(w3c)

15.请分别封装添加事件和移除事件的函数,用以解决兼容性问题

function addEvent(ele,eventName,handler){
    if(ele.attachEvent){
        ele.attachEvent("on"+eventName,function(){
            handler.call(ele) //此处使用回调函数call(),让this指向ele
        }) else if(ele.removeEventListener){
            ele.removeEventListener(eventName,handler,false);
        }
    }
}

16.写一个function,清楚字符串前后的空格(兼容所有浏览器)

if(!String.prototype.trim){

        String.prototype.trim=function(){

            retun  this.replace(/^\s+/,'').replace(/\s+$/,'');

      }

}

17.请写一个函数,用来实现对象的深拷贝

function deepClone(obj){
   return JSON.parse(JSON.stringify(obj))
}

18.移动端有哪些原生触摸事件

touch类: touchstart, touchmove, touchend, touchcancel

tap类: tap, longTap, singleTap, doubleTap

swipe类: swipe, swipeLeft, swipeRight, swipeUp, swipeDown

17.请将一个url的search部分参数值与值转换成一个json对象

function getSearch(search){
  var item
  var result={}
  if(search.indexOf("&)<0){
      item=search.split("=")
      result[item[0]]=item[1];
      return JSON.stringify(result)
  }else{
   var splitArray=search.split("&");
   for(var i=0;i<splitArray.length;i++){
     item=splitArray[i].split("=")
     result[item[0]]=item[1]
   } 
   return JSON.stringify(result);
  }
}

19.采用最少的遍历方式完成以下数组的去重

var arr=[ 1, 2, 3, 3, 4, 6, 6, 12, 12]
var result=[];
var obj={};
for(let i=0;i<arr.length;i++){
    if(!obj[arr[i]]){
        obj[arr[i]]=true;
        result.push(arr[i]);
    }
}

20.请简述下什么是同源策略

同源策略是Netscape公司提出的一个安全策略, 所有支持JavaScript的浏览器都会运用到这个安全策略. 所谓的同源是指域名,协议和端口都一致.只有当同源的情况下,才可以读取Cookie, LocalStorage和IndexDB,发送Ajax请求.浏览器这样做的目的是保证用户的数据安全.

21.简述event.stopImmediatePropagation和event.stopPropagation的不同

event.stopImmediatePropagation:阻止冒泡,且阻止该元素其他同类事件只会触发一次

event.stopPropagation:阻止事件冒泡

document.querySelector("p").addEventListener("click", function(event)
            {
                alert("我是p元素上被绑定的第一个监听函数");
            }, false);
            document.querySelector("p").addEventListener("click", function(event)
            {
                alert("我是p元素上被绑定的第二个监听函数");
                event.stopImmediatePropagation();
                //执行stopImmediatePropagation方法,阻止click事件冒泡,并且阻止p元素上绑定的其他click事件的事件监听函数的执行.
            }, false);
            document.querySelector("p").addEventListener("click", function(event)
            {
                alert("我是p元素上被绑定的第三个监听函数");
                //该监听函数排在上个函数后面,该函数不会被执行.
            }, false);
            document.querySelector("div").addEventListener("click", function(event)
            {
                alert("我是div元素,我是p元素的上层元素");
                //p元素的click事件没有向上冒泡,该函数不会被执行.
            }, false);

        22.闭包必须return出来,然后调用,此外闭包是在外函数中申明的所以通过作用域链访问到外层的变量,那么如果我不是在外函数声明的,而是与外函数平级声明,那么此时是不能访问到外函数的变量的,解决方法,用形参,把外函数变量当做形参传进来,然后在里面调用

转载于:https://my.oschina.net/u/4004801/blog/3008933

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值