面试总结

原创
2019/10/15 14:10
阅读数 55

一、2019.10.15日上午交子大道中海国际aiditaike面试总结

1、领导比较有亲合力,就是办公环境没有隔挡,不是很喜欢办公环境

2、成都这边人员太少,感觉不到规模

3、离家太远

 

1、实现clone();

   涉及知识点:

   1)、typeof 判断类型

   2)、精确的判断类型:因为type null是object,type []是object,无法通过typeof来达到精确的判断          

          obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样,这是为什么?

这是因为toString为Object的原型方法,而Array 、Function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(Function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串.....),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object上原型toString方法。

console.log(Object.prototype.toString.call("jerry"));//[object String]
console.log(Object.prototype.toString.call(12));//[object Number]
console.log(Object.prototype.toString.call(true));//[object Boolean]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call(null));//[object Null]
console.log(Object.prototype.toString.call({name: "jerry"}));//[object Object]
console.log(Object.prototype.toString.call(function(){}));//[object Function]
console.log(Object.prototype.toString.call([]));//[object Array]
console.log(Object.prototype.toString.call(new Date));//[object Date]
console.log(Object.prototype.toString.call(/\d/));//[object RegExp]

 代码实现:          

  function clone(source) {

    //如果不是object类型的话,证明是基本数据类型,直接返回
    if( typeof source != "object") {
      return source;
    }
    //给targetObj赋值,因为typeOf []和typeOf {} 返回的结果是一样的所以要用以下的方式
    var targetObj = Object.prototype.toString.call(source) == '[Object Array]' ? [] :{};
    for(var key in source) {
      //hasOwnProperty用于判断是否这个属性是这个对象的,不是原型上的,因为不复制原型上的东西
      if(source.hasOwnProperty(key)) {
        targetObj[key] = typeof source[key] == 'object' ? clone(source[key]) : source[key];
      }
    }
    return targetObj;
  }

 

    Json的实现

  function cloneByJson (source) {
    return JSON.parse(JSON.stringify(source));
  }

   

2、去除数据中的重复元素 arr = [1,1,2,3,4,4,5,5,6,6]

    1)、用es5的方式 splice


  function removeDuplicateEs6(arr) {
    //会返回一个新的数组,原数组不变
    var temparr = Array.from(new Set(arr));
  }

           

    2)、用es6中的set

  function removeDuplicateEs5(arr) {
    for(var i=0;i<arr.length;i++) {
      for(var j=i+1;j<arr.length;j++) {
        if(arr[i] === arr[j]) {
          arr.splice(j,1);
          j--
        }
      }
    }
    console.log(arr.toString())
  }

      3、Promise

            1)三种状态: promise有三种状态:pending/reslove/reject 。pending就是未决,resolve可以理解为成功,reject可以理解为拒绝。

            2)用法: Promise是javascript中异步编程的一种解决方案,和传统的异步编程方案(回调、事件)相比,使用更加简洁,功能更加强大。ES6将其写 进了语言标准,统一了语法

Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。

function runAsync(){
    let p = new Promise((resolve,reject)=>{
        if(/*异步操作成功*/){
            resolve(value);
        }else{
            reject(error);
        }
    })
    return p;
}

//情况1
runAsync()
    .then(data=>{},error=>{})
//情况2
runAsync()
    .then(data=>{})

//指定reject的回调 捕捉then方法的异常,防止阻塞。
runAsync()
    .then(data=>{})//可能出现异常错误
    .catch(error=>{})

           3)promise 与 rxjs的区别

1、rxjs可以取消subscribe,promise不可以
  setTimeout( () => {
       str.unsubscribe();
   },1000)



2、rxjs可以发射多次,promise只能发射一次
let setTime2;
    let start2 = new Observable( (observable) => {
      let count = 0;
      setTime2 = setInterval( () => {
        observable.next(count++);
      },1000)
    })
    let str2 = start2.subscribe( (num) => {
        console.log(num);
        if(num > 10){
          str2.unsubscribe();
          clearInterval(setTime2);
        } 
    })

3、rxjs 自带了许多的工具函数,如filter等


代码示例
let promise = new Promise( (resolve) => {
      setTimeout(() => {
          resolve('chen');
      },2000)
    });
    promise.then((value) => {
      console.log(value);
    })

let start = new Observable( (observer) => {
      let timeOut = setTimeout( () => {
        observer.next('chen2');
      },4000)
      
    })
    let str = start.subscribe( (value) => {
      console.log(value);
    })

          Promise 新建后就会立即执行。

let promise = new Promise(function(resolve, reject) {
  console.log('Promise');
  resolve();
});

promise.then(function() {
  console.log('resolved.');
});

console.log('Hi!');

// Promise
// Hi!
// resolved

     下面是一个用Promise对象实现的 Ajax 操作的例子。

const getJSON = function(url) {
  const promise = new Promise(function(resolve, reject){
    const handler = function() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
    const client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

  });

  return promise;
};

getJSON("/posts.json").then(function(json) {
  console.log('Contents: ' + json);
}, function(error) {
  console.error('出错了', error);
});

关于更多的Promise的知识点,请参考阮一峰ES6: http://es6.ruanyifeng.com/#docs/promise

 

3、怎么样让一个div居中

div{
    width: 100px;
    height: 100px;
    position: absolute;
    left: 50%;
    top: 50%;
    margin: -50px 0 0 -50px;
}


//css自动计算
margin: 0 auto

 

4、怎么样在html中插入10000个元素,考虑新效率

       思路: document.createDocumentFragment()  虚拟的节点对象

var d=document.createDocumentFragment();
d.appendChild(document.getElementsByTagName("LI")[0]);
d.childNodes[0].childNodes[0].nodeValue="Milk";
document.getElementsByTagName("UL")[0].appendChild(d);

      

二、2019.11.21下午3.00科学城haikangjiaotongdashuju面试总结

1、首选我对那个公司的领导的HR还是比较认可的,因为我是angular技术栈的,他们不是他们是vue和react,他们没有因为这个而把我过滤掉,这种公司是很难得的
2、对面试官的专业性,的态度还是很认可的

问题总结

1、angular的变更检测机制原理

    $scope $watch 等
2、js克隆如果出现循环引用是的解决方案

     只需要判断一个对象的字段是否引用了这个对象或这个对象的任意父级即可,可以修改上面的deepCopy函数:

     父级的引用是一种引用,非父级的引用也是一种引用,那么只要记录下对象A中的所有对象,并与新创建的对象一一对应即可。

function deepCopy2(obj, parent = null) {
    //创建一个新对象
    let result = {};
    let keys = Object.keys(obj),
        key = null,
        temp = null,
        _parent = parent;
    //该字段有父级则需要追溯该字段的父级
    while (_parent) {
        //如果该字段引用了它的父级,则为循环引用
        if (_parent.originParent === obj) {
            //循环引用返回同级的新对象
            return _parent.currentParent;
        }
        _parent = _parent.parent
    }
    for (let i = 0, len = keys.length; i < len; i++) {
        key = keys[i]
        temp = obj[key]
        // 如果字段的值也是一个新对象
        if (temp && typeof temp === 'object') {
            result[key] = deepCopy(temp, {
                //递归执行深拷贝,将同级的待拷贝对象与新对象传递给parent,方便追溯循环引用
                originParent: obj,
                currentParent: result,
                parent: parent
            });
        } else {
            result[key] = temp;
        }
    }
    return result;
}


function deepCopy3(obj) {
    // hash表,记录所有的对象的引用关系
    let map = new WeakMap();

    function dp(obj) {
        let result = null;
        let keys = Object.keys(obj);
        let key = null,
            temp = null,
            existobj = null;

        existobj = map.get(obj);
        //如果这个对象已经被记录则直接返回
        if (existobj) {
            return existobj;
        }

        result = {}
        map.set(obj, result);

        for (let i = 0, len = keys.length; i < len; i++) {
            key = keys[i];
            temp = obj[key];
            if (temp && typeof temp === 'object') {
                result[key] = dp(temp);
            } else {
                result[key] = temp;
            }
        }
        return result;
    }

    return dp(obj);
}

const obj = {
    a: {
        name: 'a'
    },
    b: {
        name: 'b'
    },
    c: {}
};
c.d.e = obj.a;

const copy = deepCopy3(obj);


3、如果 disable掉一个div,怎么样才能把他的onclick的事件不让他做出响
   其实这个问题,我后来想了一下
   1、发现disable直接return也可以
   2、css应该是有相应的属性更改disable以后元素的行为--猜的

4、柯里化

5、http cookie的理解

     会传到服务端吗

6、防抖和限流

  debounce(防抖)

    触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。

    当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。

// 防抖
function debounce(fn, wait) {    
    var timeout = null;    
    return function() {        
             if(timeout !== null)   
                 clearTimeout(timeout);        
              timeout = setTimeout(fn, wait);    
    }
}
// 处理函数
function handle() {    
    console.log(Math.random()); 
}
// 滚动事件
window.addEventListener('scroll', debounce(handle, 1000));

  throttle(节流)

高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率。

当持续触发事件时,保证一定时间段内只调用一次事件处理函数。节流通俗解释就比如我们水龙头放水,阀门一打开,水哗哗的往下流,秉着勤俭节约的优良传统美德,我们要把水龙头关小点,最好是如我们心意按照一定规律在某个时间间隔内一滴一滴的往下滴。

//节流throttle代码:
function throttle(fn,delay) {
    let canRun = true; // 通过闭包保存一个标记
    return function () {
         // 在函数开头判断标记是否为true,不为true则return
        if (!canRun) return;
         // 立即设置为false
        canRun = false;
        // 将外部传入的函数的执行放在setTimeout中
        setTimeout(() => { 
        // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。
        // 当定时器没有执行的时候标记永远是false,在开头被return掉
            fn.apply(this, arguments);
            canRun = true;
        }, delay);
    };
}
 
function sayHi(e) {
    console.log('节流:', e.target.innerWidth, e.target.innerHeight);
}
window.addEventListener('resize', throttle(sayHi,500));

总结:
函数防抖:将多次操作合并为一次操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。

函数节流:使得一定时间内只触发一次函数。原理是通过判断是否有延迟调用函数未执行。

区别: 函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。

三、oppo

1、js下载用form
2、冒泡算法

function SortBubbling() {
        var arrToBeSort = [4, 5, 4, 1, 6, 7, 9964, 34, 2,];
        for (var i = 0; i < arrToBeSort.length; i++) {
            for (var j = 1; j < arrToBeSort.length - i; j++) {
                if (arrToBeSort[j - 1] > arrToBeSort[j]) {
                    var temp;
                    temp = arrToBeSort[j - 1];
                    arrToBeSort[j - 1] = arrToBeSort[j]
                    arrToBeSort[j] = temp;
                }
            }
        }

        console.log(arrToBeSort.join(","));
    }

    SortBubbling();


3、总结一下做了些什么
4、遇到的问题

四、维创

1、事件冒泡

    参考:https://my.oschina.net/u/2285087/blog/824340

2、ul li的实现
   事件委拖

    <body>
  <div id="container">
   <ul id="list">
     <li><a href="#">Item 1</a></li>
     <li><a href="#">Item 2</a></li>
     <li><a href="#">Item 3</a></li>
     <li><a href="#">Item 4</a></li>
     ..................................
     <li><a href="#">Item 1000</a></li>
   </ul>
  </div>
</body>

document.getElementById(“list”).addEventListener(“click”, function(e) {
  console.log(e.currentTarget);  //<ul><li>...</li><ul>
  console.log(e.target);         //<a href="#">Item 2</a>
);


3、滚屏加载更多

是有办法知道你是到了底部的

用一个变量来控制

var isbool=true;//触发开关,防止多次调用事件  
 
$(window).scroll(function() {  
	if (($(this).scrollTop() + $(window).height()) >= $(document).height() && isbool==true) {    
		isbool=false;  		
		$.get("url",function(data){  			
			$("#content").append(data);//把新的内容加载到内容的后面  
			isbool=true;  
		})    
	}    
});  

4、select绑定事件

    <select name="select" onchange="t(this)">
        <option>北京</option>
        <option>天津</option>
        <option>上海</option>
        <option value="other">其他</option>
    </select>
        function t(obj)
        {
            if(obj.value=="other")
            {
                document.getElementById("a").style.display = ""
            }
            else
                document.getElementById("a").style.display = "none"
        }

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部