因為我沒Vue+Es6的經(jīng)驗救湖,所以360問的比較基礎(chǔ)。
1.由對象的拷貝引申到淺拷貝和深拷貝是如何實現(xiàn)的
除了基本類型跟null,對象之間的賦值,只是將地址指向同一個悦析,而不是真正意義上的拷貝类垫,被復(fù)制的對象改變值司光,另一個值會跟著改變。
要實現(xiàn)淺拷貝可以通過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()方法也是淺拷貝残家。
深拷貝實現(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實現(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
實現(xiàn)原型鏈繼承的本質(zhì)是:重寫原型對象售躁,代之以一個新類型的實例坞淮,換句話說原來存在于SuperType的實例中屬性和方法也存在于SubType.prototype中了。此時instance.constructor指向SuperType.
確定原型和實例的關(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() 方法允許你檢查一個對象是否存在于另一個對象的原型鏈上市袖。
alert(Object.prototype.isPrototypeOf(instance));//true;
alert(SuperType.prototype.isPrototypeOf(instance));//true;
alert(SubType.prototype.isPrototypeOf(instance));//true;
原型鏈的問題
1.原型屬性會被所有實例所共享啡直,一個實例更改了原型屬性,會導(dǎo)致所有實例引用的屬性更改。
2.在創(chuàng)建子類型的實例時付枫,不能向超類型的構(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ù)的問題
方法都在構(gòu)造函數(shù)中定義,無法實現(xiàn)函數(shù)復(fù)用阐滩,而且在超類型中定義的方法二打,對于子類型是不可見的。
③組合繼承
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最常用的繼承模式
④原型式繼承继效,借助原型基于已有的對象創(chuàng)建新對象
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'
通過例子可以看出,實例是共享person對象的装获。
ES5通過新增Object.create()方法規(guī)范了原型式繼承瑞信。這個方法接受兩個參數(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()傳入兩個參數(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)建一個僅用于封裝繼承過程的函數(shù)精肃,該函數(shù)內(nèi)部以某種方式來增強對象秤涩,最后返回這個對象。
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
在考慮對象不是自定義類型以及不是構(gòu)造函數(shù)的情況下司抱,寄生式繼承是一種有用的模式筐眷。
寄生式繼承的問題
不能做到函數(shù)復(fù)用而降低效率,與構(gòu)造函數(shù)模式類似习柠。
⑥寄生組合式繼承
構(gòu)造函數(shù)和原型鏈組合繼承存在一個問題:調(diào)用兩次構(gòu)造函數(shù)匀谣,屬性會同時存在實例和原型對象上。使用寄生和構(gòu)造函數(shù)組合式繼承可以解決這個問題资溃。
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,不借助對象
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.正則匹配電話號碼
表示以1開頭,第二位可能是3/4/5/7/8等的任意一個溶锭,在加上后面的\d表示數(shù)字[0-9]的9位宝恶,總共加起來11位結(jié)束。
/^1(3|4|5|7|8)\d{9}$/
5.js異步編程有哪些
ES 6以前:
- 回調(diào)函數(shù)
- 事件監(jiān)聽(事件發(fā)布/訂閱)
- Promise對象
ES 6:
- Generator函數(shù)(協(xié)程coroutine)
ES 7:
- async和await
①回調(diào)函數(shù)
這個很熟悉了暖途,暫不展開
②事件監(jiān)聽(觀察者模式)卑惜,解決模塊間的信息通信
首先需要把觀察者對象創(chuàng)建出來,他有一個消息容器和三個方法驻售,分別是訂閱消息方法露久,取消訂閱消息方法、發(fā)布訂閱消息方法欺栗。
//將觀察者放在閉包中毫痕,當(dāng)頁面加載便立即執(zhí)行
var Observer = (function(){
//防止消息隊列暴露而被篡改故將消息容器作為靜態(tài)私有變量保存
var _message ={};
return{
//注冊消息接口
register:function(type,fn){
//如果消息不存在
if(typeof _message[type] ==='undefined'){
_message[type] =[];
}
_message[type].push(fn);
},
//發(fā)布消息接口
fire:function(type,args){
//如果消息沒有被注冊征峦,則返回
if(!_message[type])
return;
//定義消息信息
var events ={
type:type,
args:args||[]
},
i=0,len = _message[type].length;
//遍歷消息動作
for(;i<len;i++){
//依次執(zhí)行注冊的消息對應(yīng)的隊列
_message[type][i](events);
}
},
//移除信息接口
remove:function(type,fn){
//如果消息動作隊列存在
if(_message[type] instanceof Array){
//從最后一個消息動作遍歷
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)知識,由于這部分知識比較熟悉消请,暫不展開
④Generator 函數(shù)
http://es6.ruanyifeng.com/#docs/generator(Generator函數(shù)的具體講解)
⑤ES 7中的async和await
6.getElementByClassName的兼容性問題(如何兼容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ù)組
for(var i = 0; i < list.length; i++) {//循環(huán)每一個dom元素
if(list[i].className == classn) {//判斷當(dāng)前這個元素的class名稱是否等于box
temp.push(list[i])//如果等于栏笆,將該元素添加到數(shù)組中去
}
}
return temp;//;返回給函數(shù)
}
else{
return document.getElementsByClassName(classn);
}
}
7.實現(xiàn)左右定寬臊泰,中間自適應(yīng)的三欄布局
①利用絕對定位
//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>
②利用浮動蛉加,左邊左浮動,右邊右浮動
//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>