2018-04-27 360總結(jié)

因?yàn)槲覜](méi)Vue+Es6的經(jīng)驗(yàn),所以360問(wèn)的比較基礎(chǔ)。

1.由對(duì)象的拷貝引申到淺拷貝和深拷貝是如何實(shí)現(xiàn)的

除了基本類型跟null,對(duì)象之間的賦值,只是將地址指向同一個(gè),而不是真正意義上的拷貝,被復(fù)制的對(duì)象改變值,另一個(gè)值會(huì)跟著改變。
要實(shí)現(xiàn)淺拷貝可以通過(guò)for in循環(huán),例如:

var obj = {a:10};
function copy(obj){
    var newobj = {};
    for ( var attr in obj) {
        newobj[attr] = obj[attr];
    }
    return newobj;
}
var obj2 = copy(obj);
obj2.a = 20;
alert(obj.a); //10  

ES6的Object.assign()方法也是淺拷貝。

深拷貝實(shí)現(xiàn)方法(遞歸原理)
var  obj ={a:{b:1}};
function deepCopy(obj){
  if(typeof obj !=Object){
    return obj;
  }
var newObj={};
for(var arr in obj){
  newObj[arr] = deepCopy(obj[arr]);
}
reurn newObj;
}

2.js實(shí)現(xiàn)繼承有哪幾種?

①原型鏈繼承
function SuperType(){
  this.property = true;
}
SuperType.prototype.getSuperValue = function(){
  return this.property;
}
function SubType(){
  this.property = false;
}
//繼承了SuperType
SubType.prototype= new SuperType();
SubType.prototype.getSubValue = function(){
  return this.subproperty;
};
var instance  =new SubType();
console.log(instance.getSuperValue)//true

實(shí)現(xiàn)原型鏈繼承的本質(zhì)是:重寫(xiě)原型對(duì)象,代之以一個(gè)新類型的實(shí)例,換句話說(shuō)原來(lái)存在于SuperType的實(shí)例中屬性和方法也存在于SubType.prototype中了。此時(shí)instance.constructor指向SuperType.

確定原型和實(shí)例的關(guān)系

第一種使用instanceof操作符

    alert(instance instanceof Object);//true
    alert(instance instanceof SuperType);//true
    alert(instance instanceof SubType);//true

instance本質(zhì):A instacne B就是判斷B.prototype是否存在于A的原型鏈上。Object.getPrototypeOf(A) === B.prototype(即A.proto=== B.prototype);

第二種使用isPrototypeOf()方法,isPrototypeOf() 方法允許你檢查一個(gè)對(duì)象是否存在于另一個(gè)對(duì)象的原型鏈上。

alert(Object.prototype.isPrototypeOf(instance));//true;
alert(SuperType.prototype.isPrototypeOf(instance));//true;
alert(SubType.prototype.isPrototypeOf(instance));//true;
原型鏈的問(wèn)題

1.原型屬性會(huì)被所有實(shí)例所共享,一個(gè)實(shí)例更改了原型屬性,會(huì)導(dǎo)致所有實(shí)例引用的屬性更改。
2.在創(chuàng)建子類型的實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)中傳遞參數(shù)。

②構(gòu)造函數(shù)繼承

即在子類型的構(gòu)造函數(shù)中調(diào)用超類型的構(gòu)造函數(shù)

function SuperType(){
  this.colors =['red','blue','green'];
}
function SubType(){
//繼承了SuperType
  SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push('black');
alert(instance.colors)//red,blue,green,black
var instance2 = new SubType();
alert(instance.colors)//red,blue,green

構(gòu)造函數(shù)的問(wèn)題
方法都在構(gòu)造函數(shù)中定義,無(wú)法實(shí)現(xiàn)函數(shù)復(fù)用,而且在超類型中定義的方法,對(duì)于子類型是不可見(jiàn)的。

③組合繼承
function SuperType(name){
  this.name = name;
  this.colors =['red','blue','green'];
};
SuperType.prototype.sayName = function(){
  alert(this.name);
};
function SubType(name,age){
  SuperType.call(this,name);
  this.age = age;
}
//繼承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
  alert(this.age);
}
var instance1 = new SubType('Nicholas',29);
instance1.colors.push('black');
alert(instance1.colors)//red,blue,green,black
instance1.sayName();// 'Nicholas'
instance1.sayAge();//29

var instance2 = new SubType('Greg',27);
instance2.sayName();// 'Greg'
instance2.sayAge();//27

組合繼承避免了原型鏈和借用構(gòu)造函數(shù)的缺陷,成為JS最常用的繼承模式

④原型式繼承,借助原型基于已有的對(duì)象創(chuàng)建新對(duì)象
function object(o){
  function F(){}
  F.prototype = o;
  return new F();
}

//例子
var person = {
  name:'Nicholas',
  friends:['Shelby','Court',''Van]
}
var anotherPerson = object(person);
anotherPerson.name = 'Greg';
anotherPerson.friends.push('Rob');

var yetAnotherPerson = object(person);
yetAnotherPerson .name = 'Linda';
yetAnotherPerson .friends.push('Barbie');

alert(person.friends);//'Shelly','Court','Van','Rob','Barbie'

通過(guò)例子可以看出,實(shí)例是共享person對(duì)象的。
ES5通過(guò)新增Object.create()方法規(guī)范了原型式繼承。這個(gè)方法接受兩個(gè)參數(shù):一個(gè)用作新對(duì)象原型的對(duì)象(可選)一個(gè)為新對(duì)象定義額外屬性的對(duì)象。在傳入一個(gè)參數(shù)時(shí),Object.create()和object()方法行為一致。

var person = {
  name:'Nicholas',
  friends:['Shelby','Court',''Van]
}
var anotherPerson = Object.create(person);
anotherPerson.name = 'Greg';
anotherPerson.friends.push('Rob');

var yetAnotherPerson = Object.create(person);
yetAnotherPerson .name = 'Linda';
yetAnotherPerson .friends.push('Barbie');

alert(person.friends);//'Shelly','Court','Van','Rob','Barbie'

當(dāng)Object.create()傳入兩個(gè)參數(shù)時(shí):

var person = {
  name:'Nicholas',
  friends:['Shelby','Court',''Van]
}
var anotherPerson = Object.create(person,{
  name:{
    value:'Greg'  
}
})
alert(anotherPerson.name);//'Greg'
⑤寄生式繼承

寄生式繼承與原型式繼承緊密相關(guān)。創(chuàng)建一個(gè)僅用于封裝繼承過(guò)程的函數(shù),該函數(shù)內(nèi)部以某種方式來(lái)增強(qiáng)對(duì)象,最后返回這個(gè)對(duì)象。

function createAnother(original){
  var clone = object(original)//或者Object.create(original);
  clone.sayHi = function(){
    alert('Hi');
  };
  return clone;
}

var person = {
  name:'Nicholas',
  friends:['Shelly','Court','Van']
}
var anotherPerson = createAnother(person);
anotherPerson.sayHi();//Hi

在考慮對(duì)象不是自定義類型以及不是構(gòu)造函數(shù)的情況下,寄生式繼承是一種有用的模式。

寄生式繼承的問(wèn)題

不能做到函數(shù)復(fù)用而降低效率,與構(gòu)造函數(shù)模式類似。

⑥寄生組合式繼承

構(gòu)造函數(shù)和原型鏈組合繼承存在一個(gè)問(wèn)題:調(diào)用兩次構(gòu)造函數(shù),屬性會(huì)同時(shí)存在實(shí)例和原型對(duì)象上。使用寄生和構(gòu)造函數(shù)組合式繼承可以解決這個(gè)問(wèn)題。

function inheritPrototype(SubType,SuperType){
  var prototype = object(SuperType.prototype);
  prototype.constructor = SubType;
  subType.prototype= prototype;
}

function SuperType(name){
  this.name = name;
  this.colors =['red','blue','green']
}
SuperType.prototype.sayName = function(){
  alert(this.name)
}
function SubType(name,age){
  SuperType.call(this,name);
  this.age = age;
}
//關(guān)鍵代碼
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge= function(){
  alert(this.age);
}

2.數(shù)組的去重

①利用lastIndexOf,不借助對(duì)象
var arr1=[],arr=[1,2,2,2,3,4];
arr.filter(function(value,key){
  if(arr.lastIndexOf(value) ==key){
    return true;
  }else{
    return false;
  }
})
②利用數(shù)組的sort和reduce方法
var arr=[1,2,1,2,3,3,4,4,5,6,7];
var nArr = arr.sort().reduce(function(initValue,current){
   if(initValue[initValue.length-1]!==current){
      initValue.push(current);
}
return initValue;
},[])

3.閉包題

function A(){
  var i=0;
  return function B(){
    console.log(i++);
  }
}
var a = A();
a();//0
a();//1

var b = A();
b();//0
b();//1

4.正則匹配電話號(hào)碼

表示以1開(kāi)頭,第二位可能是3/4/5/7/8等的任意一個(gè),在加上后面的\d表示數(shù)字[0-9]的9位,總共加起來(lái)11位結(jié)束。

/^1(3|4|5|7|8)\d{9}$/

5.js異步編程有哪些

ES 6以前:

  • 回調(diào)函數(shù)
  • 事件監(jiān)聽(tīng)(事件發(fā)布/訂閱)
  • Promise對(duì)象

ES 6:

  • Generator函數(shù)(協(xié)程coroutine)

ES 7:

  • async和await
①回調(diào)函數(shù)

這個(gè)很熟悉了,暫不展開(kāi)

②事件監(jiān)聽(tīng)(觀察者模式),解決模塊間的信息通信

首先需要把觀察者對(duì)象創(chuàng)建出來(lái),他有一個(gè)消息容器和三個(gè)方法,分別是訂閱消息方法,取消訂閱消息方法、發(fā)布訂閱消息方法。

//將觀察者放在閉包中,當(dāng)頁(yè)面加載便立即執(zhí)行
var Observer = (function(){
  //防止消息隊(duì)列暴露而被篡改故將消息容器作為靜態(tài)私有變量保存
  var _message ={};
  return{
    //注冊(cè)消息接口
    register:function(type,fn){
      //如果消息不存在
      if(typeof _message[type] ==='undefined'){
        _message[type] =[];
      }
        _message[type].push(fn);
    },
    //發(fā)布消息接口
    fire:function(type,args){
      //如果消息沒(méi)有被注冊(cè),則返回
      if(!_message[type])
        return;
      //定義消息信息
      var events ={
        type:type,
        args:args||[]
      },
      i=0,len = _message[type].length;
      //遍歷消息動(dòng)作
      for(;i<len;i++){
        //依次執(zhí)行注冊(cè)的消息對(duì)應(yīng)的隊(duì)列
       _message[type][i](events);
      }
    },
    //移除信息接口
    remove:function(type,fn){
      //如果消息動(dòng)作隊(duì)列存在
      if(_message[type] instanceof Array){
        //從最后一個(gè)消息動(dòng)作遍歷
        var i= _message[type].length-1;
        for(;i>=0;i--){
          _message[type][i] ===fn&&_message[type].splice(i,1);
        }
      }
    }
  }
})()

Observer.register('test',function(e){console.log(e.type,e.args.msg)});
Observer.fire('test',{msg:'chu'})
// test chu
③promise相關(guān)知識(shí),由于這部分知識(shí)比較熟悉,暫不展開(kāi)
④Generator 函數(shù)

http://es6.ruanyifeng.com/#docs/generator(Generator函數(shù)的具體講解)

⑤ES 7中的async和await

6.getElementByClassName的兼容性問(wèn)題(如何兼容IE8)

function getclass(classn) {//創(chuàng)建函數(shù) 傳入形參
    if(!document.getElementsByClassName) {//判斷document.getElementsByClassName方法是否支持
        var list = document.getElementsByTagName("*");//先取得所有的dom標(biāo)簽元素
        //              alert(list.length)
        var temp = [];//創(chuàng)建臨時(shí)數(shù)組
        for(var i = 0; i < list.length; i++) {//循環(huán)每一個(gè)dom元素
            if(list[i].className == classn) {//判斷當(dāng)前這個(gè)元素的class名稱是否等于box
                temp.push(list[i])//如果等于,將該元素添加到數(shù)組中去
            }

        }
         return temp;//;返回給函數(shù)
    }
    else{

        return document.getElementsByClassName(classn); 
    }
}

7.實(shí)現(xiàn)左右定寬,中間自適應(yīng)的三欄布局

①利用絕對(duì)定位
//css
.left{
    width: 100px;
    background: red;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
}
.right{
    width: 100px;
    background: blue;
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
}
.center{
    background: green;
    margin-left: 100px;
    margin-right: 100px;
    top: 0;
    bottom:0;
}
//html
<div class="left">1</div>
<div class="center">2</div>
<div class="right">3</div> 
②利用浮動(dòng),左邊左浮動(dòng),右邊右浮動(dòng)
//css
.left{
    float: left;
    width: 100px;
    background: red;
}
.right{
    float: right;
    width: 100px;
    background: green;
}
//html(注意html的排列順序,中間的元素放在了最后面)
<div class="left">1</div>
<div class="right">3</div>
<div class="center">2</div>

如果不使中間的元素放在最后面可為中間元素加上此樣式
.center{
  display:inline-block;
}
③使用彈性盒布局
//css
.main{
    display: flex;
}
.left{
    width: 100px;
    background: red
}
.center{
    flex:1;
}
.right{
    width: 100px;
    background: blue;
}
//html
<div class="main">
   <div class="left">1</div>
   <div class="center">2</div>
   <div class="right">3</div>   
</div>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容