js&jq面試筆記(下)

js&jq面試筆記,該部分爲下部分。javascript

字符串相關

一、定義一個方法,用於將string中的每一個字符之間加一個空格,並輸出

如:'hello' -> 'h e l l o'

function joinSpace(str){
    return str.split('').join(' ')
}

二、JavaScript中如何檢測一個變量是一個String類型?請寫出函數實現

方法1
function isString(obj){
    return typeof(obj) === "string"? true: false;
    // returntypeof obj === "string"? true: false;
}

方法2
function isString(obj){
    return obj.constructor === String? true: false;
}

方法3
function isString(obj){
     return Object.prototype.toString.call(obj) === "[object String]"?true:false;
}
如:
var isstring = isString('xiaoming');
console.log(isstring);  // true

三、請用js去除字符串空格?

方法一:使用replace正則匹配的方法
    去除全部空格: 
    str = str.replace(/\s*/g,"");      
    
    去除兩頭空格: 
    str = str.replace(/^\s*|\s*$/g,"");
    
    去除左空格: 
    str = str.replace( /^\s*/, 「」);
    
    去除右空格: 
    str = str.replace(/(\s*$)/g, "");
    
    str爲要去除空格的字符串,實例以下:
    var str = " 23 23 ";
    var str2 = str.replace(/\s*/g,"");
    console.log(str2); // 2323

方法二:使用str.trim()方法
    str.trim() //侷限性:沒法去除中間的空格,實例以下:
    var str = "   xiao  ming   ";
    var str2 = str.trim();
    console.log(str2);   //xiao  ming 
    同理:
    str.trimLeft(),str.trimRight() //分別用於去除字符串左右空格。

方法三:使用jquery,$.trim(str)方法
    $.trim(str) 侷限性:沒法去除中間的空格,實例以下:
    var str = "   xiao  ming   ";
    var str2 = $.trim(str)
    console.log(str2);   //  xiao  ming

四、你如何獲取瀏覽器URL中查詢字符串中的參數?

//測試地址爲:http://www.runoob.com/jquery/misc-trim.html?channelid=12333&name=xiaoming&age=23
function showWindowHref(){
    var sHref = window.location.href;
    var args = sHref.split('?');
    if(args[0] == sHref){
        return "";
    }
    var arr = args[1].split('&');
    var obj = {};
    for(var i = 0;i< arr.length;i++){
        var arg = arr[i].split('=');
        obj[arg[0]] = arg[1];
    }
    return obj;
}
var href = showWindowHref(); // obj
console.log(href['name']); // xiaoming

五、js 字符串操做函數

//這裏只是列舉了經常使用的字符串函數,具體使用方法,請參考網址。
concat()        將兩個或多個字符的文本組合起來,返回一個新的字符串。
indexOf()       返回字符串中一個子串第一處出現的索引。若是沒有匹配項,返回 -1 。
charAt()        返回指定位置的字符。
lastIndexOf()   返回字符串中一個子串最後一處出現的索引,若是沒有匹配項,返回 -1 。
match()         檢查一個字符串是否匹配一個正則表達式。
substr()        返回從string的startPos位置,長度爲length的字符串
substring()     返回字符串的一個子串。傳入參數是起始位置和結束位置。
slice()         提取字符串的一部分,並返回一個新字符串。
replace()       用來查找匹配一個正則表達式的字符串,而後使用新字符串代替匹配的字符串。
search()        執行一個正則表達式匹配查找。若是查找成功,返回字符串中匹配的索引值。不然返回 -1 。
split()         經過將字符串劃分紅子串,將一個字符串作成一個字符串數組。
length          返回字符串的長度,所謂字符串的長度是指其包含的字符的個數。
toLowerCase()   將整個字符串轉成小寫字母。
toUpperCase()   將整個字符串轉成大寫字母。

六、判斷一個字符串中出現次數最多的字符,統計這個次數

var str = 'asdfssaaasasasasaa';
var json = {};
for (var i = 0; i < str.length; i++) {
    if(!json[str.charAt(i)]){   //判斷json中是否存在當前str.charAr(i)的值
       json[str.charAt(i)] = 1;   //若是不存在,則將其存放在json中,而且賦值爲1,至關於出現的次數爲1
    }else{
       json[str.charAt(i)]++;  //若是存在,則這個字符的值加1,至關於次數加1
    }
};
var iMax = 0;
var iIndex = '';
for(var i in json){
    if(json[i]>iMax){   //判斷當前json中的鍵值(至關於當前鍵所在字符的次數)是否大於iMax
         iMax = json[i];
         iIndex = i;
    }
}        
console.log('出現次數最多的是:'+iIndex+'出現'+iMax+'次');

數組(Array)對象

一、Array相關的屬性和方法

  • Array 對象屬性
constructor 返回對建立此對象的數組函數的引用。

var test=new Array();
if (test.constructor==Array){
    document.write("This is an Array");
}
    
length 設置或返回數組中元素的數目。

prototype 使您有能力向對象添加屬性和方法。
  • Array 對象方法
join() 把數組的全部元素放入一個字符串。元素經過指定的分隔符進行分隔。
    var arr = ['xiao','lin','qiqi','mingtian'];
    var arr2 = arr.join(',');
    console.log(arr2); // 根據','隔開返回的字符串爲:"xiao,lin,qiqi,mingtian"
    
pop() 刪除並返回數組的最後一個元素。 
    var arr = [2,3,4,5];
    var arr2 = arr.pop();
    console.log(arr2); // 刪除的數組的最後一個元素爲:5
    console.log(arr);  // 刪除元素以後的數組爲:[2, 3, 4]
    
shift() 刪除並返回數組的第一個元素
    var arr = [2,3,4,5];
    var arr2 = arr.shift();
    console.log(arr2); // 刪除的數組的第一個元素爲:2
    console.log(arr);  // 刪除元素以後的數組爲:[3, 4,5]
    
push() 向數組的末尾添加一個或更多元素,並返回新的長度。
    var arr = [2,3,4,5];
    var arr2 = arr.push(6);
    console.log(arr2);  // 返回的數組長度:5 
    console.log(arr);  // [2, 3, 4, 5, 6]
    
unshift() 向數組的開頭添加一個或更多元素,並返回新的長度。
    var arr = ['xiao','ming','qiqi','aiming'];
    var arr1 = arr.unshift('lang');
    console.log(arr1);  // 返回的數組的長度:  5
    console.log(arr);  //向數組開頭添加元素返回的結果:["lang", "xiao", "ming", "qiqi", "aiming"]
    
reverse() 顛倒數組中元素的順序。
    var arr = [2,3,4,5];
    arr.reverse();
    console.log(arr);   //  [5, 4, 3, 2]
    
slice() 從某個已有的數組返回選定的元素
    var arr = [2,3,4,5];
    var arr2 = arr.slice(1,3);
    console.log(arr2);  // 截取區間返回的數組爲:[3, 4]
    console.log(arr);  // [2, 3, 4, 5]
    
sort() 對數組的元素進行排序
    藉助排序函數,實現數值由小到大排序
    function sortNumber(a,b){
        return a - b
    }
    var arr = [23,30,42,5];
    var arr2 = arr.sort(sortNumber);
    console.log(arr2);  // [5, 23, 30, 42]
    console.log(arr);   // [5, 23, 30, 42]

    藉助排序函數,實現數值由大到小排序
    function sortNumber(a,b){
        return b - a
    }
    var arr = [23,30,42,5];
    var arr2 = arr.sort(sortNumber);
    console.log(arr2);  // [42, 30, 23, 5]
    console.log(arr);  // [42, 30, 23, 5]

splice() 刪除元素,並向數組添加新元素。
    語法:arrayObject.splice(index,howmany,item1,.....,itemX)
    index:必需。整數,規定添加/刪除項目的位置,使用負數可從數組結尾處規定位置。
    howmany:必需。要刪除的項目數量。若是設置爲 0,則不會刪除項目。
    item1, ..., itemX:可選。向數組添加的新項目。

    // 建立一個新數組,並向其添加一個元素
    var arr = [1,2,3,4];
    arr.splice(2,0,5);
    console.log(arr);  // [1, 2, 5, 3, 4]

    // 刪除位於 index 2 的元素,並添加一個新元素來替代被刪除的元素:
    var arr = [1,2,3,4];
    arr.splice(2,1,5);
    console.log(arr);  // [1, 2, 5, 4]
    
toString() 把數組轉換爲字符串,並返回結果。
    var arr = ['xiao','ming','qiqi','aiming'];
    arr.toString();
    console.log(arr);  // ["xiao", "ming", "qiqi", "aiming"]

二、編寫一個方法 去掉一個數組的重複元素

方法一
var arr = [0,2,3,4,4,0,2];
var obj = {};
var tmp = [];
for(var i = 0 ;i< arr.length;i++){
   if( !obj[arr[i]] ){
      obj[arr[i]] = 1;
      tmp.push(arr[i]);
   }
}
console.log(tmp);       //結果以下: [0, 2, 3, 4]

方法二
var arr = [2,3,4,4,5,2,3,6];
var arr2 = [];
for(var i = 0;i< arr.length;i++){
    if(arr2.indexOf(arr[i]) < 0){
        arr2.push(arr[i]);
    }
}
console.log(arr2);      //結果爲:[2, 3, 4, 5, 6]

方法三
var arr = [2,3,4,4,5,2,3,6];
var arr2 = arr.filter(function(element,index,self){
    return self.indexOf(element) === index;
});
console.log(arr2);      //結果爲:[2, 3, 4, 5, 6]

方法四:(ES6提供了新的數據結構 Set)
let unique= [...new Set(array)];
let unique= [...new Set([2,3,4,4,5,2,3,6])];
console.log(unique)

三、求數組的最值?

求數組最大值:Math.max.apply(null,arr);
var arr = [3,43,23,45,65,90];
var max = Math.max.apply(null,arr);
console.log(max);
// 90

求數組最小值:Math.min.apply(null,arr);
var arr = [3,43,23,45,65,90];
var min = Math.min.apply(null,arr);
console.log(min);
// 3

四、數組排序相關

選擇排序
/**
*以一個角標的元素和其餘元素進行比較。
*在內循環第一次結束,最值出現的頭角標位置上。
*/
function selectSort(array) {
    if (Object.prototype.toString.call(array).slice(8, -1) === 'Array') {
        var len = array.length, temp;
        for (var i = 0; i < len - 1; i++) {  //輪數
            var min = array[i];
            for (var j = i + 1; j < len; j++) {  //第一個與第二個比較
                if (array[j] < array[i]) {
                    temp = array[i];
                    array[i] = array[j];
                    array[j] = temp;
                }
            }
        }
        return array;
    } else {
        return 'array is not an Array!';
    }
}

冒泡排序
/**
*比較方式:相鄰兩個元素進行比較,若是後一個比前一個小,換位置。
*原理:內循環結束一次,最值出如今尾角標位置。
*/
function bubbleSort(array) {
    if (Object.prototype.toString.call(array).slice(8, -1) === 'Array') {
        var len = array.length, temp;
        for(var j=0;j<len-1;j++){
        //兩兩比較,若是前一個比後一個大,則交換位置。
           for(var i=0;i<len-1-j;i++){  //-i:讓每次參與比較的元素減小。-1:避免角標越界。
                if(arr[i]>arr[i+1]){
                    var temp = arr[i];
                    arr[i] = arr[i+1];
                    arr[i+1] = temp;
                }
            } 
        }
        return array;
    } else {
        return 'array is not an Array!';
    }
}


二分插入排序
/**
*爲了提升查找效率,可以使用折半查找的方式,注意:這種查找只對有序的數組有效。這種方式也叫二分查找法。
*/
function binaryInsertionSort(array) {
    if (Object.prototype.toString.call(array).slice(8, -1) === 'Array') {
        for (var i = 1; i < array.length; i++) {
            var key = array[i], left = 0, right = i - 1;
            while (left <= right) {
                var middle = parseInt((left + right) / 2);
                if (key < array[middle]) {
                    right = middle - 1;
                } else {
                    left = middle + 1;
                }
            }
            for (var j = i - 1; j >= left; j--) {
                array[j + 1] = array[j];
            }
            array[left] = key;
        }
        return array;
    } else {
        return 'array is not an Array!';
    }
}

五、數組的翻轉(非reverse())

方法一:
var arr = [1,2,3,4];
var arr2 = [];
while(arr.length) {
    var num = arr.pop(); //刪除數組最後一個元素並返回被刪除的元素
    arr2.push(num);
}
console.log(arr2);
// [4, 3, 2, 1]

方法二:
var arr = [1,2,3,4];
var arr2 = [];
while(arr.length){
    var num = arr.shift(); //刪除數組第一個元素並返回被刪除的元素
    arr2.unshift(num);
}
console.log(arr2);

六、在Javascript中什麼是僞數組?如何將僞數組轉化爲標準數組?

  • 僞數組(類數組):沒法直接調用數組方法或指望length屬性有什麼特殊的行爲,但仍能夠用真正數組遍歷方法來遍歷它們。

典型的是函數的argument參數,還有像調用getElementsByTagName,document.childNodes之類的,它們都返回NodeList對象都屬於僞數組。css

a.使用Array.prototype.slice.call();        
    Array.prototype.slice.call({  
     0:"likeke",  
     1:12,  
     2:true,  
     length:3  
    });  
    //["likeke", 12, true]
    
b.使用[].slice.call(),瞭解js原型鏈的都知道,實際上這種方法和第一中方法是同樣的,但上面第一種方式相對效率更高。
    [].slice.call({  
     0:"likeke",  
     1:12,  
     2:true,  
     length:3  
    });  
    //["likeke", 12, true] 
    
c. 使用ES6中Array.from方法;
    Array.from({  
     0:"lk",  
     1:12,  
     2:2013,  
     3:"長安大學",  
     length:4  
    });  
    //["lk", 12, 2013, "長安大學"]

對象相關

一、獲取JavaScript對象鍵名

var obj = {name: 'wan',age: 20, sex: 'male'};  
var objKey = [];  
for(var item in obj){  
  if(obj.hasOwnProperty(item)){  
    objKey.push(item);  
  }  
}  
//for(var item in obj){  
//    objKey.push(item);  
//}  
console.log(objKey);//["name", "age", "sex"]

二、call和apply的區別

  • 語法一:func.call(thisObj,a,b,c...) || func.apply(thisObj,array)
    定義:將函數(方法) func 綁定到對象 thisObj 上去運行,改變了函數func 原有的 this 的指向,this指向了對象thisObj(js中的函數是對象,函數名是對 Function 對象的引用)
  • 語法二:obj.call(thisObj,a,b,c...) || obj.apply(thisObj,array)
    定義:將對象 obj 的屬性和方法添加到對象 thisObj 上,即 thisObj 繼承了 obj

    區別:call的參數個數,從第二個開始 大於等於 0個,爲單個變量;apply的參數只有兩個,第二個參數爲一個數組,即array = [a,b,c...];html

實例一:借調方法,對象sub借調對象add的方法add(函數也是對象)

    function add(a,b){return a+b}

    function sub(a,b){return a-b}

    add.call(sub,3,1)//4

    sub.call(add,3,1)//2

    add.call(sub,3,1) === add(3,1)

實例二:改變this指向

    function a(){console.log(this)}

    var obj = {}

    a()//window

    a.call()//window

    a.call(obj)//obj

實例三:實現繼承

    function Animal(name){this.name=name;this.showName=function(){alert(this.name)}}
    function Cat(name){

        Animal.call(this,name); //將Animal對象的屬性和方法應用到Cat上,所以Cat繼承了Animal的全部屬性和方法
    }
    var cat = new Cat(「Black Cat」);
    cat.showName(); //Black Cat

實例四:多重繼承


    function add(a,b){return a+b}

    function sub(a,b){return a-b}

    function calc(a,b){

        add.call(this)

        sub.call(this)

    }

三、js中改變this指向的方法

call、apply、bind,this老是指向調用它的對象

四、爲下面的類增長一個方法method1

var A = function(){}
A.prototype.method1 = function(a,b){return a+b}

五、實現Parent類和Child類,並創建Parent和Child的繼承關係

  • 面向對象的基本特徵有:封閉、繼承、多態。
function Parent(){
    this.surname = 'wan';
    this.work = function(){console.log('i like work')}
}
function Child(){}

原型鏈繼承:Child.prototype = new Parent()
    實例化:let person = new Child();
    console.log(person.surname);//wan
    person.work();//i like work

構造函數繼承:function Child(){Parent.call(this)}

組合繼承:
    function Child(){
        Parent.call(this);//繼承屬性
    }
    Child.prototype = new Parent();//繼承方法

原型式繼承:
    function object(obj){
      function Func(){};
      Func.prototype = obj;
      return new Func();
    }
    var Child = object(Parent);

寄生式繼承:

寄生組合式繼承:

六、解釋原型和原型鏈

  • 原型:即原型對象,原型對象上定義方法和屬性的目的是爲了被子類繼承和使用。原型鏈的造成真正是靠__proto__ 而非prototype
  • 原型鏈:每一個對象都有原型,對象的原型指向原型對象,即子對象的原型指向父對象,父對象的原型指向爺爺對象,這種原型層層鏈接起來的就構成了原型鏈。

七、定義一個類的私有屬性和公有屬性

function Person(){
    var sex = 'man';//var 私有
    this.surnname = 'wan';//this 公有
}

八、實現一個函數clone,能夠對JavaScript中的5種主要的數據類型(包括Number、String、Object、Array、Boolean)進行值複製。

(Object.prototype.toString.call()方法及應用)
/**
 * 對象克隆
 * 支持基本數據類型及對象
 * 遞歸方法
 */
function clone(obj) {
    var o;
    switch (typeof obj) {
        case "undefined":
            break;
        case "string":
            o = obj + "";
            break;
        case "number":
            o = obj - 0;
            break;
        case "boolean":
            o = obj;
            break;
        case "object": // object 分爲兩種狀況 對象(Object)或數組(Array)
            if (obj === null) {
                o = null;
            } else {
                if (Object.prototype.toString.call(obj).slice(8, -1) === "Array") {
                    o = [];
                    for (var i = 0; i < obj.length; i++) {
                        o.push(clone(obj[i]));
                    }
                } else {
                    o = {};
                    for (var k in obj) {
                        o[k] = clone(obj[k]);
                    }
                }
            }
            break;
        default:
            o = obj;
            break;
    }
    return o;
}

//測試
var a=[12,34,'123'];
console.log(clone(a));
var b=null;
console.log(clone(b));
var c={1:'a',2:'b',3:'c'};
console.log(clone(c));
var d=1;
console.log(clone(d));

九、建立對象

  • 使用Object構造函數或對象字面量均可以建立對象,但缺點是建立多個對象時,會產生大量的重複代碼,所以下面介紹可解決這個問題的建立對象的方法
一、工廠模式
    function createPerson(name, age, job) {
        var o = new Object();
        o.name = name;
        o.age = age;
        o.job = job;
        o.getName = function () {
            return this.name;
        }
        return o;//使用return返回生成的對象實例
    }
    var person = createPerson('Jack', 19, 'SoftWare Engineer');
    建立對象交給一個工廠方法來實現,能夠傳遞參數,但主要缺點是沒法識別對象類型,由於建立對象都是使用Object的原生構造函數來完成的。

二、構造函數模式
    function Person(name,age,job){
        this.name = name;
        this.age = age;
        this.job = job;
        this.getName = function () {
            return this.name;
        }
    }
    var person1 = new Person('Jack', 19, 'SoftWare Engineer');
    var person2 = new Person('Liye', 23, 'Mechanical Engineer');
    使用自定義的構造函數(與普通函數同樣,只是用它來建立對象),定義對象類型(如:Person)的屬性和方法。它與工廠方法區別在於:

    沒有顯式地建立對象,直接將屬性和方法賦值給this對象;沒有return語句;
    此外,要建立Person的實例,必須使用new關鍵字,以Person函數爲構造函數,傳遞參數完成對象建立;實際建立通過如下4個過程:

    建立一個對象
    將函數的做用域賦給新對象(所以this指向這個新對象,如:person1)
    執行構造函數的代碼
    返回該對象
    上述由Person構造函數生成的兩個對象person1與person2都是Person的實例,所以可使用instanceof判斷,而且由於全部對象都繼承Object,所以person1 instanceof Object也返回真:

    alert(person1 instanceof Person);//true;
    alert(person2 instanceof Person);//true;
    alert(person1 instanceof Object);//true;
    alert(person1.constructor === person2.constructor);//ture;
    雖然構造函數方式比較不錯,但也存在缺點,那就是在建立對象時,特別針對對象的屬性指向函數時,會重複的建立函數實例,以上述代碼爲基礎,能夠改寫爲:

    function Person(name,age,job){
        this.name = name;
        this.age = age;
        this.job = job;
        this.getName = new Function () {//改寫後效果與原代碼相同,不過是爲了方便理解
            return this.name;
        }
    }
    上述代碼,建立多個實例時,會重複調用new Function();建立多個函數實例,這些函數實例還不是一個做用域中,固然這通常不會有錯,但這會形成內存浪費。
    固然,能夠在函數中定義一個getName = getName的引用,而getName函數在Person外定義,這樣能夠解決重複建立函數實例問題,但在效果上並無起到封裝的效果,以下所示:

    function Person(name,age,job){
        this.name = name;
        this.age = age;
        this.job = job;
        this.getName = getName;
    }
    function getName() {//處處是代碼,看着亂!!
        return this.name;
    }
    
    
三、原型模式
    JS每一個函數都有一個prototype(原型)屬性,這個屬性是一個指針,指向一個對象,它是全部經過new操做符使用函數建立的實例的原型對象。
    原型對象最大特色是,全部對象實例共享它所包含的屬性和方法,也就是說,全部在原型對象中建立的屬性或方法都直接被全部對象實例共享。

    function Person(){}
    Person.prototype.name = 'Jack';//使用原型來添加屬性
    Person.prototype.age = 29;
    Person.prototype.getName = function(){
        return this.name;
    }
    var person1 = new Person();
    alert(person1.getName());//Jack
    var person2 = new Person();
    alert(person1.getName === person2.getName);//true;共享一個原型對象的方法

    原型是指向原型對象的,這個原型對象與構造函數沒有太大關係,惟一的關係是函數的prototype是指向這個原型對象!而基於構造函數建立的對象實例也包含一個內部指針爲:[[prototype]]指向原型對象。

實例屬性或方法的訪問過程是一次搜索過程:
    首先從對象實例自己開始,若是找到屬性就直接返回該屬性值;
    若是實例自己不存在要查找屬性,就繼續搜索指針指向的原型對象,在其中查找給定名字的屬性,若是有就返回;
    基於以上分析,原型模式建立的對象實例,其屬性是共享原型對象的;但也能夠本身實例中再進行定義,在查找時,就不從原型對象獲取,而是根據搜索原則,獲得本實例的返回;簡單來講,就是實例中屬性會屏蔽原型對象中的屬性;

原型與in操做符
    一句話:不管原型中屬性,仍是對象實例的屬性,均可以使用in操做符訪問到;要想判斷是不是實例自己的屬性可使用object.hasOwnProperty(‘attr’)來判斷;

原生對象中原型
    原生對象中原型與普通對象的原型同樣,能夠添加/修改屬性或方法,如如下代碼爲全部字符串對象添加去左右空白原型方法:
    
    String.prototype.trim = function(){
        return this.replace(/^\s+/,'').replace(/\s+$/,'');
    }
    var str = ' word space ';
    alert('!'+str.trim()+'!');//!word space!
    
    原型模式的缺點,它省略了爲構造函數傳遞初始化參數,這在必定程序帶來不便;另外,最主要是當對象的屬性是引用類型時,它的值是不變的,老是引用同一個外部對象,全部實例對該對象的操做都會其它實例:

    function Person() {    }
    Person.prototype.name = 'Jack';
    Person.prototype.lessons = ['Math','Physics'];
    var person1 = new Person();
    person1.lessons.push('Biology');
    var person2 = new Person();
    alert(person2.lessons);//Math,Physics,Biology,person1修改影響了person2

    
四、組合構造函數及原型模式
    目前最爲經常使用的定義類型方式,是組合構造函數模式與原型模式。構造函數模式用於定義實例的屬性,而原型模式用於定義方法和共享的屬性。結果,每一個實例都會有本身的一份實例屬性的副本,但同時又共享着對方方法的引用,最大限度的節約內存。此外,組合模式還支持向構造函數傳遞參數,可謂是集兩家之所長。

    function Person(name, age, job) {
        this.name = name;
        this.age = age;
        this.job = job;
        this.lessons = ['Math', 'Physics'];
    }
    Person.prototype = {
        constructor: Person,//原型字面量方式會將對象的constructor變爲Object,此外強制指回Person
        getName: function () {
            return this.name;
        }
    }
    var person1 = new Person('Jack', 19, 'SoftWare Engneer');
    person1.lessons.push('Biology');
    var person2 = new Person('Lily', 39, 'Mechanical Engneer');
    alert(person1.lessons);//Math,Physics,Biology
    alert(person2.lessons);//Math,Physics
    alert(person1.getName === person2.getName);//true,//共享原型中定義方法

    在所接觸的JS庫中,jQuery類型的封裝就是使用組合模式來實例的!!!


五、動態原型模式
    組合模式中實例屬性與共享方法(由原型定義)是分離的,這與純面嚮對象語言不太一致;動態原型模式將全部構造信息都封裝在構造函數中,又保持了組合的優勢。

    其原理就是經過判斷構造函數的原型中是否已經定義了共享的方法或屬性,若是沒有則定義,不然再也不執行定義過程。該方式只原型上方法或屬性只定義一次,且將全部構造過程都封裝在構造函數中,對原型所作的修改能當即體現全部實例中:

    function Person(name, age, job) {
        this.name = name;
        this.age = age;
        this.job = job;
        this.lessons = ['Math', 'Physics'];
    }
    if (typeof this.getName != 'function') {//經過判斷實例封裝
      Person.prototype = {
        constructor: Person,//原型字面量方式會將對象的constructor變爲Object,此外強制指回Person
        getName: function () {
          return this.name;
        }
      }
    }
    var person1 = new Person('Jack', 19, 'SoftWare Engneer');
    person1.lessons.push('Biology');
    var person2 = new Person('Lily', 39, 'Mechanical Engneer');
    alert(person1.lessons);//Math,Physics,Biology
    alert(person2.lessons);//Math,Physics
    alert(person1.getName === person2.getName);//true,//共享原型中定義方法

jQuery相關

一、jQuery爲DOM元素綁定點擊事件的方法和區別

.click(function(){}) 

    .bind({'click mouseleave',function(){}},{'click mouseleave',function(){}}) //在.bind()綁定事件的時候,這些元素必須已經存在。

    .on() //爲動態綁定事件

    .one("click", function() {alert("This will be displayed only once.");});//綁定一個事件,而且只運行一次,而後刪除本身,

二、jQuery 庫中的 $() 是什麼?

  $() 函數是 jQuery() 函數的別稱。$() 函數用於將任何對象包裹成 jQuery 對象,接着你就被容許調用定義在 jQuery 對象上的多個不一樣方法。前端

能夠將一個選擇器字符串傳入` $()` 函數,它會返回一個包含全部匹配的 DOM 元素數組的 jQuery 對象。

三、如何找到全部 HTML select 標籤的選中項?

$('[name=selectname] :selected')

四、$(this)this 關鍵字在 jQuery 中有何不一樣?

  • $(this) 返回一個 jQuery 對象,你能夠對它調用多個 jQuery 方法,好比用 text() 獲取文本,用val() 獲取值等等。

    而 this 表明當前元素,它是 JavaScript 關鍵詞中的一個,表示上下文中的當前 DOM 元素。你不能對它調用 jQuery 方法,直到它被 $() 函數包裹,例如 $(this)。java

五、jquery怎麼移除標籤onclick屬性?

得到a標籤的onclick屬性: $("a").attr("onclick")

刪除onclick屬性:$("a").removeAttr("onclick");

設置onclick屬性:$("a").attr("onclick","test();");

六、jquery中addClass,removeClass,toggleClass的使用。

$(selector).addClass(class):爲每一個匹配的元素添加指定的類名

$(selector).removeClass(class):從全部匹配的元素中刪除所有或者指定的類,刪除class中某個值;

$(selector).toggleClass(class):若是存在(不存在)就刪除(添加)一個類

$(selector).removeAttr(class);刪除class這個屬性;

七、JQuery有幾種選擇器?

(1)、基本選擇器:#id,class,element,*;

(2)、層次選擇器:parent > child,prev + next ,prev ~ siblings

(3)、基本過濾器選擇器::first,:last ,:not ,:even ,:odd ,:eq ,:gt ,:lt

(4)、內容過濾器選擇器: :contains ,:empty ,:has ,:parent

(5)、可見性過濾器選擇器::hidden ,:visible

(6)、屬性過濾器選擇器:[attribute] ,[attribute=value] ,[attribute!=value] ,[attribute^=value] ,[attribute$=value] ,[attribute*=value]

(7)、子元素過濾器選擇器::nth-child ,:first-child ,:last-child ,:only-child

(8)、表單選擇器: :input ,:text ,:password ,:radio ,:checkbox ,:submit 等;

(9)、表單過濾器選擇器::enabled ,:disabled ,:checked ,:selected

八、jQuery中的Delegate()函數有什麼做用?

  • delegate()會在如下兩個狀況下使用到:jquery

    一、若是你有一個父元素,須要給其下的子元素添加事件,這時你可使用delegate()了,代碼以下:css3

    `$("ul").delegate("li", "click", function(){ $(this).hide(); });`

    二、當元素在當前頁面中不可用時,可使用delegate()web

九、$(document).ready()方法和window.onload有什麼區別?

(1)、window.onload 方法是在網頁中全部的元素(包括元素的全部關聯文件)徹底加載到瀏覽器後才執行的。

(2)、$(document).ready() 方法能夠在DOM載入就緒時就對其進行操縱,並調用執行綁定的函數。

十、如何用jQuery禁用瀏覽器的前進後退按鈕?

  $(document).ready(function() {
    window.history.forward(1);
    //OR window.history.forward(-1);
  });

十一、 jquery中$.get()提交和$.post()提交有區別嗎?

  • 相同點:都是異步請求的方式來獲取服務端的數據;
  • 異同點:

    一、請求方式不一樣:$.get() 方法使用GET方法來進行異步請求的。$.post() 方法使用POST方法來進行異步請求的。面試

    二、參數傳遞方式不一樣:get請求會將參數跟在URL後進行傳遞,而POST請求則是做爲HTTP消息的實體內容發送給Web服務器的,這種傳遞是對用戶不可見的。ajax

    三、數據傳輸大小不一樣:get方式傳輸的數據大小不能超過2KB 而POST要大的多

    四、安全問題: GET 方式請求的數據會被瀏覽器緩存起來,所以有安全問題。

十二、寫出一個簡單的$.ajax()的請求方式?

$.ajax({
    url:'http://www.baidu.com',
    type:'POST',
    data:data,
    cache:true,
    headers:{},
    beforeSend:function(){},
    success:function(){},
    error:function(){},
    complete:function(){}
});

1三、jQuery的事件委託方法bind 、live、delegate、on之間有什麼區別?

  • (1)、bind 【jQuery 1.3以前】

    定義和用法:主要用於給選擇到的元素上綁定特定事件類型的監聽函數;
    
    語法:bind(type,[data],function(eventObject));
    
    特色:
    
      (1)、適用於頁面元素靜態綁定。只能給調用它的時候已經存在的元素綁定事件,不能給將來新增的元素綁定事件。
    
      (2)、當頁面加載完的時候,你才能夠進行bind(),因此可能產生效率問題。
    
    實例以下:$( "#members li a" ).bind( "click", function( e ) {} );
  • (2)、live 【jQuery 1.3以後】

    定義和用法:主要用於給選擇到的元素上綁定特定事件類型的監聽函數;
    
    語法:live(type, [data], fn);
    
    特色:
    
      (1)、live方法並無將監聽器綁定到本身(this)身上,而是綁定到了this.context上了。
    
      (2)、live正是利用了事件委託機制來完成事件的監聽處理,把節點的處理委託給了document,新添加的元素沒必要再綁定一次監聽器。
    
      (3)、使用live()方法但卻只能放在直接選擇的元素後面,不能在層級比較深,連綴的DOM遍歷方法後面使用,即$(「ul」").live...能夠,但$("body").find("ul").live...不行; 
    
    實例以下:$( document ).live( "click", "#members li a", function( e ) {} );
  • (3)、delegate 【jQuery 1.4.2中引入】

    定義和用法:將監聽事件綁定在就近的父級元素上
    
    語法:delegate(selector,type,[data],fn)
    
    特色:
    
      (1)、選擇就近的父級元素,由於事件能夠更快的冒泡上去,可以在第一時間進行處理。
    
      (2)、更精確的小範圍使用事件代理,性能優於.live()。能夠用在動態添加的元素上。
    
    實例以下:
    
    $("#info_table").delegate("td","click",function(){/*顯示更多信息*/});
    
    $("table").find("#info").delegate("td","click",function(){/*顯示更多信息*/});
  • (4)、on 【1.7版本整合了以前的三種方式的新事件綁定機制】

    定義和用法:將監聽事件綁定到指定元素上。
    
    語法:on(type,[selector],[data],fn)
    
    實例以下:$("#info_table").on("click","td",function(){/*顯示更多信息*/});參數的位置寫法與delegate不同。
    
    說明:on方法是當前JQuery推薦使用的事件綁定方法,附加只運行一次就刪除函數的方法是one()。
    
    總結:.bind(), .live(), .delegate(),.on()分別對應的相反事件爲:.unbind(),.die(), .undelegate(),.off()

開發及性能優化

一、規避javascript多人開發函數重名問題

命名空間
封閉空間
js模塊化mvc(數據層、表現層、控制層)
seajs
變量轉換成對象的屬性
對象化

二、請說出三種減低頁面加載時間的方法

壓縮css、js文件
合併js、css文件,減小http請求
外部js、css文件放在最底下
減小dom操做,儘量用變量替代沒必要要的dom操做

三、你所瞭解到的Web攻擊技術

  • (1)XSS(Cross-Site Scripting,跨站腳本攻擊):指經過存在安全漏洞的Web網站註冊用戶的瀏覽器內運行非法的HTML標籤或者JavaScript進行的一種攻擊。
  • (2)SQL注入攻擊
  • (3)CSRF(Cross-Site Request Forgeries,跨站點請求僞造):指攻擊者經過設置好的陷阱,強制對已完成的認證用戶進行非預期的我的信息或設定信息等某些狀態更新。

四、web前端開發,如何提升頁面性能優化?

  • 內容方面:

    1.減小 HTTP 請求 (Make Fewer HTTP Requests)
    
    2.減小 DOM 元素數量 (Reduce the Number of DOM Elements)
    
    3.使得 Ajax 可緩存 (Make Ajax Cacheable)
  • 針對CSS:

    1.把 CSS 放到代碼頁上端 (Put Stylesheets at the Top)
    
    2.從頁面中剝離 JavaScript 與 CSS (Make JavaScript and CSS External)
    
    3.精簡 JavaScript 與 CSS (Minify JavaScript and CSS)
    
    4.避免 CSS 表達式 (Avoid CSS Expressions)
  • 針對JavaScript :

    1. 腳本放到 HTML 代碼頁底部 (Put Scripts at the Bottom)
    
    2. 從頁面中剝離 JavaScript 與 CSS (Make JavaScript and CSS External)
    
    3. 精簡 JavaScript 與 CSS (Minify JavaScript and CSS)
    
    4. 移除重複腳本 (Remove Duplicate Scripts)
  • 面向圖片(Image):

    1.優化圖片
    
    2 不要在 HTML 中使用縮放圖片
    
    3 使用恰當的圖片格式
    
    4 使用 CSS Sprites 技巧對圖片優化

五、前端開發中,如何優化圖像?圖像格式的區別?

  • 優化圖像:

    一、不用圖片,儘可能用css3代替。 好比說要實現修飾效果,如半透明、邊框、圓角、陰影、漸變等,在當前主流瀏覽器中均可以用CSS達成。
    
    二、 使用矢量圖SVG替代位圖。對於絕大多數圖案、圖標等,矢量圖更小,且可縮放而無需生成多套圖。如今主流瀏覽器都支持SVG了,因此可放心使用!
    
    3.、使用恰當的圖片格式。咱們常見的圖片格式有JPEG、GIF、PNG。
    
    基本上,內容圖片多爲照片之類的,適用於JPEG。
    
    而修飾圖片一般更適合用無損壓縮的PNG。
    
    GIF基本上除了GIF動畫外不要使用。且動畫的話,也更建議用video元素和視頻格式,或用SVG動畫取代。
    
    四、按照HTTP協議設置合理的緩存。
    
    五、使用字體圖標webfont、CSS Sprites等。
    
    六、用CSS或JavaScript實現預加載。
    
    七、WebP圖片格式能給前端帶來的優化。WebP支持無損、有損壓縮,動態、靜態圖片,壓縮比率優於GIF、JPEG、JPEG2000、PG等格式,很是適合用於網絡等圖片傳輸。
  • 圖像格式的區別:

    矢量圖:圖標字體,如 font-awesome;svg 
    
    位圖:gif,jpg(jpeg),png
  • 區別:

    1 、gif:是是一種無損,8位圖片格式。具備支持動畫,索引透明,壓縮等特性。適用於作色彩簡單(色調少)的圖片,如logo,各類小圖標icons等。
    
    二、JPEG格式是一種大小與質量相平衡的壓縮圖片格式。適用於容許輕微失真的色彩豐富的照片,不適合作色彩簡單(色調少)的圖片,如logo,各類小圖標icons等。
    
    三、png:PNG能夠細分爲三種格式:PNG8,PNG24,PNG32。後面的數字表明這種PNG格式最多能夠索引和存儲的顏色值。
    
    關於透明:PNG8支持索引透明和alpha透明;PNG24不支持透明;而PNG32在24位的PNG基礎上增長了8位(256階)的alpha通道透明;
  • 優缺點:

    一、能在保證最不失真的狀況下儘量壓縮圖像文件的大小。
    
    二、對於須要高保真的較複雜的圖像,PNG雖然能無損壓縮,但圖片文件較大,不適合應用在Web頁面上。

ES5和ES6

一、ES5和ES6的類

ES5的類
function Person(name) {
    this.name = name; 
}

Person.prototype.sayHello = function(){
    return 'Hi, I am ' + this.name;
}

ES6的類
class Person {
    constructor(name){
        this.name = name;
    }
    sayHello(){
        return 'Hi, I am ' + this.name;
    } 
}

typeof Person; //'function'

調用的方式都是一致的:
var me = new Person('Yecao');

二、ES5的繼承和ES6的繼承有什麼區別?

  • ES5的繼承時經過prototype或構造函數機制來實現。ES5的繼承實質上是先建立子類的實例對象,而後再將父類的方法添加到this上(Parent.apply(this))。
  • ES6的繼承機制徹底不一樣,實質上是先建立父類的實例對象this(因此必須先調用父類的super()方法),而後再用子類的構造函數修改this。
ES6繼承
class Father{
    constructor(name){
        this.name = name;
    }
    getName(){
        console.log(this.name);
    }
    //  這裏是父類的f方法
    f(){
        console.log('fffffffffffffffffffffff');
    }
}

class Son extends Father{
    constructor(name,age){
        super(name); // HACK: 這裏super()要在第一行
        this.age = age;
    }
    getAge(){
        console.log(this.age);
    }
    //  子類的f方法
    f(){
        console.log('sssssssssssssssssssssss');
    }
}
var s1 = new Son('張一',12);
s1.getName();
s1.getAge();
console.log(s1.__proto__);          //  爲Son,不用修正
s1.f();                             //  打印ssssssssssssss
s1.__proto__ = new Father();        //  改變s1的原型指向,改成Father
s1.f();                             // 打印ffffffffffffff
console.log(s1.__proto__);          // 爲Father

ES5繼承
function Father(name){
  this.name = name;
}
function Son(name,age){
  Father.call(this,name);
  this.age = age;
}
Father.prototype.getName = function(){
  console.log(this.name);
}
// 這裏注意原型繼承要在,實例化s1變量以前,若是要使用原型鏈上的方法的話,子類的原型是父類的一個實例
Son.prototype = new Father;

// 修正構造器,這裏注意要將Son的構造器指向賦值爲Son,不然,打印出來的s1是Father對象
Son.prototype.constructor = Son;
Son.prototype.getAge = function(){
  console.log(this.age);
}
var s1 = new Son('李四',22);
console.log(s1);                            // Son {name:'李四',age:22}
s1.getName();                               // 李四
console.log(Son.prototype.constructor);     // Son
console.log(s1.constructor);                // Son,若是不糾正,則爲Father
s1.getAge();                                // 22

//HACK:這裏經過__proto__這個s1實例的屬性找到了Son的prototype,併爲其添加了say的方法
s1.__proto__.say = function(){  
  console.log('hhhhhhhhhhhhhhhhhhhhhhhh');
}
s1.say()                                    // 打印 hhhhhhhhhhhhhhh

// NOTE: __proto__這個屬性是具體到某個實例化後的對象纔有的屬性,指向他所屬的類的原型
console.log(new Son().__proto__);           // 爲Son對象

二、ES6 Set和Map

Map和Set都叫作集合,可是他們也有所不一樣。Set常被用來檢查對象中是否存在某個鍵名,Map集合常被用來獲取已存的信息。

  • 一、set相似於數組,可是成員的值都是惟一的,沒有重複的值。
    Set 實例的方法分爲兩大類:操做方法(用於操做數據)和遍歷方法(用於遍歷成員)。
四個操做方法。
 add(value):添加某個值,返回Set結構自己。
 delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功。
 has(value):返回一個布爾值,表示該值是否爲Set的成員。
 clear():清除全部成員,沒有返回值。


Set 結構的實例有四個遍歷方法,能夠用於遍歷成員。
keys():返回鍵名的遍歷器
values():返回鍵值的遍歷器
entries():返回鍵值對的遍歷器
forEach():使用回調函數遍歷每一個成員
  • 二、Set相似於數組,而Map就相似於鍵值對(Key, Value);

它相似於對象,也是鍵值對的集合,可是「鍵」的範圍不限於字符串,各類類型的值(包括對象)均可以看成鍵。
Map有size()屬性,查看Map對象大小,set(key , value) , get(Key), delete(key) , has(key) ,clear()方法。

Map 結構原生提供三個遍歷器生成函數和一個遍歷方法。
 keys():返回鍵名的遍歷器。
 values():返回鍵值的遍歷器。
 entries():返回全部成員的遍歷器。
 forEach():遍歷 Map 的全部成員。
相關文章
相關標籤/搜索