js:基礎面試題

總結前端基礎面試題範圍

  • JS基礎(原型、原型鏈、做用域、閉包、異步、單線程)
  • JS-WEB-API(DOM操做、Ajax、事件綁定)
  • JS-開發環境(版本管理、模板化、打包工具、頁面渲染、性能優化)
列舉幾個面試題

JS基礎

JS中使用typeof能獲得的哪些類型?
7種:number、string、undefined、boolean、symbol、object、function

typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof b // b 沒有聲明,可是還會顯示 undefined

typeof [] // 'object'
typeof {} // 'object'
typeof console.log // 'function'

typeof null // 'object'
複製代碼
什麼時候使用===什麼時候使用==?
if (obj.a == null) {
    // 這裏至關於obj.a === null || obj.a === undefined, 簡寫形式
    // jquery源碼中推薦的寫法
}
=== 全等:值和類型都相等
== 等:值相等 null == undefined
複製代碼
JS中的內置函數
Object、Array、Boolean、Number、String、Function、Date、RegExp、Error
複製代碼
JS按存儲方式區分變量類型
基本類型有6種,分別是undefined,null,boolean,string,number,symbol(ES6新增)。
雖然 typeof null 返回的值是 object,可是null不是對象,而是基本數據類型的一種。
基本數據類型存儲在棧內存,存儲的是值。
複雜數據類型的值存儲在堆內存,地址(指向堆中的值)存儲在棧內存。當咱們把對象賦值給另一個變量的時候,複製的是地址,指向同一塊內存空間,當其中一個對象改變時,另外一個對象也會變化。
// 值類型
var a = 10;
var b = a;
a = 11;
console.log(b); // 10

// 引用類型
var obj1 = { x: 100 }
var obj2 = obj1;
obj1.x = 200;
console.log(obj2.x) // 200

在條件判斷時,除了 undefined, null, false, NaN, '', 0, -0,其餘全部值都轉爲 true,包括全部對象。
複製代碼
變量類型和計算
1.變量計算-強制類型轉換
(1).字符串拼接
var a=100+10; // 110
var b=100+'10'; // '10010'
(2).==運算符
100 == '100'  // true
0 == ''  // true
null == undefined // true
(3).if語句
1.var a=true;
if(a){
   //....
}
2.var b=100;
if(b){
    //...
}
3.var c= '';
if(c){
    //..
}
(4).邏輯運算
console.log(10 && 0); // 0
console.log('' || 'abc'); // 'abc'
console.log(!window.abc); // true
複製代碼
如何理解JSON
JSON只不過是一個JS對象而已

JSON.stringify({a:10, b:20});
JSON.parse('{"a":10, "b": 20}')
複製代碼
原型構造函數
// 構造函數
function Foo(name, age) {
    this.name = name;
    this.age = age;
    this.class = "class-1";
    //return this 默認有這一行
}
var f = new Foo("cl", 29); // 建立多個對象

// 構造函數-擴展
1.var a={}實際上是var a=new Object()的語法糖。
2.var a=[]實際上是var a=new Array()的語法糖。
3.function Foo(){....}實際上是var Foo=new Fuction(...)
4.使用instanceof判斷一個函數是不是一個變量的構造函數。

// 原型規則和示例
1.全部的引用類型(數組、對象、函數 ),都具備對象特性,便可自由擴展屬性(除了"null"以外)。
var obj={};obj.a=100;
var arr=[];arr.a=100;
function fn(){}  fn.a=100;

2.全部的引用類型(數組、對象、函數 ),都有一個__proto__屬性,屬性值是一個普通的對象。
console.log(obj.__proto__);
console.log(arr.__proto__);
console.log(fn.__proto__);

3.全部的函數,都有一個prototype屬性,屬性值也是一個普通的對象。
console.log(fn.prototype)

4.全部的引用類型(數組、對象、函數 ),__proto__屬性值指向它的構造函數的"prototype"屬性值。
console.log(obj.__proto__===Object.prototype);

5.當試圖獲得一個對象的某個屬性時,若是這個對象自己沒有這個屬性,那麼會去它的__proto__(即它的構造函數的prototype)中尋找。

//構造函數
function Foo(name, age){
    this.name=name;
}
Foo.prototype.alertName = function(){
    alert(this.name);
}
//建立示例
var f=new Foo('小林');
f.printName=function(){
    console.log(this.name);
}
//測試
f.printName();
f.alertName();
f.toString();//要去f.__proto__.__proto__中查找。
複製代碼
原型鏈

instanceof
1.f instanceof Foo的判斷邏輯是:
2.f的__proto__一層一層往上,可否對應到Foo.prototype。
3.再試着判斷f instanceof Object。
複製代碼
如何準確判斷一個變量是數組類型
var arr = [];
arr instanceof Array // true
typeof arr // object、typeof是沒法判斷是不是數組的
複製代碼
寫一個原型鏈繼承的列子
function Animal() {
    this.eat = function() {
        console.log("animal eat");
    }
}

function Dog() {
    this.back = function() {
        console.log("dog back")
    }
}

Dog.prototype = new Animal();

var hashiqi = new Dog();


function Elem(id) {
    this.elem = document.getElementById(id);
}
Elem.prototype.html = function (val){
var elem = this.elem;
if(val){
    elem.innerHTML = val;
    return this; //鏈式操做
}else {
    return elem.innerHTML;
}
}
Elem.prototype.on = function (type, fn){
var elem = this.elem;
elem.addEventListener(type, fn);
}
var div1 = new Elem('box');
//        console.log(div1.html());
//         div1.html('<p>2222</p>');
//         div1.on("click", function(){
//             alert("111");
//         })
div1.html('<p>2222</p>').on("click", function(){
   alert("this.text()");
})
複製代碼
描述new一個對象的過程
1.新生成了一個對象
2.連接到原型
3.綁定 this
4.返回新對象

function create() {
    // 建立一個空的對象
    let obj = new Object()
    // 得到構造函數
    let Con = [].shift.call(arguments)
    // 連接到原型
    obj.__proto__ = Con.prototype
    // 綁定 this,執行構造函數
    let result = Con.apply(obj, arguments)
    // 確保 new 出來的是個對象
    return typeof result === 'object' ? result : obj
}
複製代碼
this指向
(1).this要執行時才能確認值,定義時沒法確認
1.做爲構造函數執行
function Foo(name){
    this.name=name;
}
var f=new Foo("小林")

2.做爲對象屬性執行
var obj = {
      name:"A",
      printName: function(){
            console.log(this.name);
     }
}
obj.printName()

3.做爲普通函數執行
function fn(){
      console.log(this)//window
}
fn()

4.call、Apple、bind
function fn1(name, age){
      alert(name);
      console.log(this)//window
}
fn1.call({x:100}, "zhangsan", 20);//{x:100}this指向
fn1.call({x:100}, ["zhangsan", 20]);//{x:100}this指向
var fn2 = function(name, age){
      alert(name);
      console.log(this);
}.bind({y:200})
fn2('zhangsan', 20)


var a={
    name: "A",
    fn: function(){
          console.log(this.name);
    }
}
a.fn() // this===a
a.fn.call({name:'B'}) // this ==={name: 'B'}
var fn1 = a.fn;
fn1 // this===window
複製代碼
做用域
(1).沒有塊級做用域。
if(true){
    var name="zhangsan";
}
console.log(name);

(2).只有函數和全局做用域。
var a=100;
function fn(){
  var a=200;
  console.log('fn', a);
}
console.log('global', a);
fn();

(3).做用域鏈
var a=100;
function fn(){
    var b=200;
    console.log(a)//當前做用域沒有定義的變量,即「自由變量」
    console.log(b)
}
複製代碼
執行上下文
(1).範圍:一段<script>或者一個函數。
(2).全局:變量定義、函數聲明。一段<script>。
(3).函數:變量定義、函數聲明、this、argument、函數
(4).函數聲明和函數表達式的區別。
console.log(a);  //undefined
var a = 100;

fn('zhangsan')  // 'zhangsan'   20
function fn(name) {
      age=20;
      console.log(name,age);
      var age;
}
複製代碼
閉包
1.函數做爲返回值。
function f1(){
    var a=10;
    return function (){
         console.log(a)//自由變量,父做用域尋找
   }
}
var f =f1();
var a=2000;
f();// 10

2.函數做爲函數傳遞。
function f1(){
    var a=10;
    return function (){
         console.log(a)//自由變量,父做用域尋找
   }
}
var f =f1();
function f2(fn){
    var a=200;
    fn();
}
f2(f1);
複製代碼
說一下對變量提高的理解

詳解: www.cnblogs.com/liuhe688/p/…html

下面這個ul,請寫出代碼,讓點擊每一列的時候alert其index?
<ul id="test">
    <li>這是第一條</li>
    <li>這是第二條</li>
    <li>這是第三條</li>
    <li>這是第四條</li>
    <li>這是第五條</li>
</ul>

<script>
    //第一種方式,加入index屬性
    // window.onload = function() {
    //     var test = document.getElementById('test');
    //     var list = test.getElementsByTagName('li');
    //     for(var i=0; i<list.length; i++){
    //         list[i].setAttribute('index',i);
    //         list[i].addEventListener("click", function(){
    //           console.log(this.getAttribute('index'), 'index');
    //         })
    //     }
    // };
    // 第二種方式,用let申明變量
    // window.onload = function() {
    //     const test = document.getElementById('test');
    //     const list = test.getElementsByTagName('li');
    //     for(let i=0; i<list.length; i++){
    //         list[i].addEventListener("click", function(){
    //           console.log(i, 'let');
    //         })
    //     }
    // };
    //方法3,使用閉包的方式
    // window.onload = function() {
    //     var test = document.getElementById('test');
    //     var list = test.getElementsByTagName('li');
    //     for(var i=0; i<list.length; i++) {
    //         list[i].addEventListener("click", function(num) {
    //             return function() {
    //                 console.log(num);
    //             }
    //         }(i))
    //     }
    // }
    // 方法4
    // window.onload = function() {
    //     var test = document.getElementById('test');
    //     var list = test.getElementsByTagName('li');
    //     for(var i=0; i<list.length; i++){
    //         list[i].index=i
    //         list[i].addEventListener("click", function(e){
    //           console.log(e.target.index);
    //         })
    //     }
    // };
</script>
複製代碼
如何理解做用域

詳解: www.cnblogs.com/smyhvae/p/8…前端

異步和單線程
1.什麼時候須要異步
    (1).在可能發生等待的狀況。
    (2).等待過程當中不能像alert同樣阻塞程序運行。
    (3).所以,因此的'等待的狀況'都須要異步。
2.異步的場景
    (1).定時任務:setTimeout,setInverval。
    (2).網絡請求:ajax請求,動態<img>加載。
    (3).事件綁定
3.同步和異步的區別是什麼
    (1).同步會阻塞代碼執行,而異步不會。
    (2).alert是同步,setTimeout是異步。

console.log(100);
setTimeout(function() {
    console.log(200);
})
console.log(300);

1.執行第一行,打印100;
2.執行setTimeout後,傳入setTimeout的函數會被暫存起來,不會當即執行(單線程的特色,不能同時幹兩件事);
3.執行最後一行,打印300;
4.待全部程序執行完,處於空閒狀態時,會立馬看有木有暫存起來的要執行;
5.發現暫存起來的setTimeout中的函數無需等待時間,就當即過來執行

複製代碼
獲取當天格式的日期
function formatDate(dt) {
      dt = !dt ? new Date() : dt;
      let year = dt.getFullYear();
      let month = dt.getMonth() + 1;
      let data = dt.getDate();
      month = month < 10 ? ('0' + month) : month;
      data = data < 10 ? ('0' + data) : data;
      //強制轉換
      return year + "-" + month + "-" + data;
}    
let dt = new Date();
console.log(formatDate(dt));
複製代碼
獲取隨機數,要求是長度一直的字符串格式
var num = Math.random();
num = num + '0000000000';
num = num.slice(0, 10);
console.log(num);
複製代碼
寫一個能遍歷對象和數組的forEach函數
function forEach(obj, fn) {
    if (obj instanceof Array) {
        // 準確判斷是否是數組
        obj.forEach(function(item, index){
            fn(index, item);
        })
    } else {
        // 不是數組就是對象
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                fn(key, obj[key]);
            }
           
        }
    }
}

// 數組
const arr = [1,2,3];
forEach(arr, function(index, item) {
    console.log(index, item);
})

//對象
const obj = { x:100, y: 200};
forEach(obj, function(key, value){
    console.log(key, value);
})
複製代碼
數組API
1.forEach
var arr=[1,2,3];
arr.forEach(function(item, index){
        //遍歷數組的全部元素
         console.log(index, item);
})

2.every
var arr=[1,2,3];
var result=arr.every(function (item, index){
      //用來判斷全部的數組元素,都知足一個條件
      if(item < 4){
                 return ture;
        }
})
console.log(result);

3.some
var arr=[1,2,3];
var result = arr.some(function (item, index){
     //用來判斷全部的數組元素,只要有一個知足條件便可
     if(item < 2){
             return ture
      }
})
console.log(result);

4.sort
var arr=[1,4,2,3,5];
var arr2 = arr.sort(function(a, b){
        //從小到大排序
       return a-b;
       //從大到小排序
       // return b-a
})
console.log(arr2);

5.map
var arr=[1,2,3,4];
var arr2 = arr.map(function(item, index){
       //將元素從新組裝,並返回
       return '<b>'+item+'</b>';
})
console.log(arr2);

6.filter
var arr=[1,2,3];
var arr2=arr.filter(function(item, index){
       //經過某一個條件過濾數組
       if(item >= 2){
              return true;
       }
})
console.log(arr2);
複製代碼

JS-WEB-API

DOM節點操做

DOM能夠理解爲:瀏覽器把拿到的html代碼,結構化一個瀏覽器能識別而且js可操做的一個模型而已。node

<div id="box">
    <p class="container"></p>
    <p></p>
    <p></p>
</div>
<script>
 var box = document.getElementById("box"); // 元素
 var boxList = document.getElementsByTagName("p"); // 集合
 console.log(boxList.length);
 console.log(boxList[0]);

 var box = document.querySelector("#box");
 console.log(box);

 var container = document.getElementsByClassName(".container");
 console.log(container);

//  property
 var box = document.querySelectorAll("p"); //集合
 console.log(box);
 var p = box[0];
 console.log(p.style.width); // 獲取樣式
 p.style.width = "100px"; // 修改樣式
 console.log(p.className); // 獲取class
 p.className = "p1"; // 修改class

 // 獲取nodeName 和 nodeType
 console.log(p.nodeName);
 console.log(p.nodeType);

// Attribute
 var box = document.querySelectorAll("p"); //集合
 var p = box[0];
 p.getAttribute("data-name");
 p.setAttribute("data-name", "imooc");
 p.getAttribute("style");
 p.setAttribute("style","font-size: 30px");
 
 
// 新增節點
var box = document.getElementById("box");
// 添加新節點
var p = document.createElement("p");
p.innerHTML = "this is p";
box.appendChild(p); // 添加新建立的元素
// 移動已有節點
var p1 = document.getElementById("p1");
box.appendChild(p1);

// 獲取父元素和子元素
var box = document.getElementById("box");
var parent = box.parentElement;
var child = box.childNodes;
box.removeChild(child[0]);

// 刪除節點
var box =document.getElementById("box");
var child = box.childNodes;
box.removeChild(child[0]);

</script>
複製代碼
DOM節點的Attribute和property有何區別
1.property只是一個JS對象的屬性的修改
2.Attribute是對html標籤屬性的修改
複製代碼
如何檢測瀏覽器的類型
var ua = navigator.userAgent;
var isChrom = ua.indexOf("Chrome");
console.log(isChrom);

console.log(location.href); // 網址
console.log(location.protocol); //協議https
console.log(location.pathname); // 域名/p/4d6b43fda11a
console.log(location.search);
console.log(location.hash);
history.back();// 返回上頁面,頁面不刷新
history.forward(); //加載 history 列表中的下一個 URL。
複製代碼
通用綁定事件的函數
<div id="box">
     <a >2</a>
     <a >3</a>
     <a >4</a>
 </div>
<script>
    function bindEvent(elem, type, selector, fn) {
        if (fn == null) {
            fn = selector;
            selector = null;
        }
        elem.addEventListener(type, function (e) {
            let target;
             if (selector) {
                 target = e.target;
                 if (target.matches(selector)) {
                     fn.call(target, e);
                 } else {
                     fn(e);
                 }
             }
        })
    }
let box = document.getElementById("box");
bindEvent(box, 'click', 'a', function(e){
    console.log(this.innerHTML);
})
<script>
複製代碼
代理的好處
1.代碼簡潔
2.減小瀏覽器內存佔用
複製代碼
相關文章
相關標籤/搜索