javascript知識回顧

陳林007發表於2019-04-16
1.知識點
  • 原型、原型鏈、作用域、閉包
  • DOM操作、Ajax、事件繫結
  • 版本管理、模組化、打包工具
  • 頁面渲染、效能優化
2.列如
3.變數型別和計算
1.變數型別
(1).值型別(null、undefined、boolean、number、string,symbol)
var a=100; 
var b=a;
 a=200;
console.log(b); //100
(2).引用型別(物件、陣列、函式)
var a={age:20};
var b=a;
b.age=21;
console.log(b); // 21
(3).typeof運算子詳解
typeof undefined //undefined
typeof 'abc' // string
typeof 123 //number
typeof true // boolean
typeof {} // object
typeof [] // object
typeof null // object
typeof console.log // function
2.變數計算-強制型別轉換
(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
3.何時使用===和==
if(obj.a == null){
      //這裡相當於obj.a === null || obj.a===undefined,簡寫形式
      //這是jQuery原始碼中推薦的寫法
}
4.JS中的內建函式
Object
Array
Boolean
Number
String
Function
Date
RegExp
Error
5.如何理解JSON
JSON.stringify({a:10,b:20})
JSON.parse('{"a":10,"b":20}')
複製程式碼
4.原型和原型鏈
  • 如何準確判斷一個變數是陣列型別?
  • 寫一個原型鏈繼承的例子?
  • 描述new一個物件的過程?
  • zepto(或其它框架)原始碼中如何使用原型鏈?
  • 建構函式
  • 建構函式-擴充套件
  • 原型規則和示例
  • 原型鏈
  • instanceof
1.建構函式
function Foo(name,age){
      this.name=name;
      this.age=age;
      this.class="class-1;
      //return this //預設有這一行
}
var f = new Foo("小林",20);//建立多個物件
2.建構函式-擴充套件
(1).var a={}其實是var a=new Object()的語法糖。
(2).var a=[]其實是var a=new Array()的語法糖。
(3).function Foo(){....}其實是var Foo=new Fuction(...)
(4).使用instanceof判斷一個函式是否是一個變數的建構函式。
3.原型規則和示例
(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 F('小林');
f.printName=function(){
    console.log(this.name);
}
//測試
f.printName();
f.alertName();
f.toString();//要去f.__proto__.__proto__中查詢。
複製程式碼

6.png

迴圈物件自身的屬性
for (var item in f) {
    if(f.hasOwnProperty(item)){
        console.log(item);
    }
}
複製程式碼
5.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 Aniaml () {
    this.eat = function () {
        console.log('animal eat')
    }
}

// 狗
function Dog () {
    this.bark = function () {
        console.log('dog bark')
    }
}

Dog.prototype = new Animal()

var hashiqi = new Dog()
複製程式碼
描述new一個物件的過程
  • 新生成了一個物件
  • 連結到原型
  • 繫結 this
  • 返回新物件
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
}
複製程式碼
6.原型繼承例項
1.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()");
           })
複製程式碼

######7.作用域和閉包

1.執行上下文
(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;
}
2.this指向
(1).this要執行時才能確認值,定義時無法確認
(2).場景
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.apple({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
3.作用域
(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)
}
4.閉包
(1).閉包的使用場景
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);
複製程式碼
建立10個標籤點選的時候彈出來對應的序號
var i;
for (i = 0; i<10; i++) {
    (function (i){
        var a = document.createElement('a');
        a.innerHTML = i + '<br>';
        a.addEventListener('click', function(e){
            e.preventDefault();
            alert(i);
        })
        document.body.appendChild(a)
    })(i)
}
複製程式碼
實際開發中閉包的應用
 // 閉包實際應用中主要用於封裝變數,收檢許可權
 function isFirstLoad () {
     var list = [];
     return function (id) {
         if (list.indexOf(id) >= 0) {
             return false;
         } else {
             list.push(id);
             return true;
         }
     }
 }
 
 // 使用
 var firstLoad = isFirstLoad();
 firstLoad(10) // true
 firstLoad(10) // false
 firstLoad(20) // true 
複製程式碼
8.非同步和單執行緒
  • 同步和非同步的區別是什麼?分別舉一個同步和非同步的例子?
  • 一個關於setTimeout的筆試題
  • 前端使用非同步的場景有哪些?
  • 什麼是非同步(對比同步)?
  • 非同步和單執行緒?
1.何時需要非同步
(1).在可能發生等待的情況。
(2).等待過程中不能像alert一樣阻塞程式執行。
(3).因此,所以的'等待的情況'都需要非同步。
2.非同步的場景
(1).定時任務:setTimeout,setInverval。
(2).網路請求:ajax請求,動態<img>載入。
(3).事件繫結
3.同步和非同步的區別是什麼
(1).同步會阻塞程式碼執行,而非同步不會。
(2).alert是同步,setTimeout是非同步。
4.非同步和單執行緒
(1).執行第一行,列印100;
(2).執行setTimeout後,傳入setTimeout的函式會被暫存起來,不會立即執行(單執行緒的特點,不能同時幹兩件事)
(3).執行最後一行,列印300
(4).待所有程式執行完,處於空閒狀態時,會立馬看有沒有暫存起來的要執行。
(2).發現暫存起來的setTimeout中的函式無需等待時間,就立即過來執行。

複製程式碼
9.日期、Math、陣列api、物件api
題目
  • 獲取2017-06-10格式的日期
  • 獲取隨機數,要求是長度一直的字串格式
  • 寫一個能遍歷物件和陣列的通用forEach函式
獲取2017-06-10格式的日期:
function formatDate(dt) {
    if(!dt) {
        dt = new Date();
    }
    let year = dt.getFullYear();
    let month = dt.getMonth()-1;
    let data = dt.getDate();
    month = month < 10 ? ('0' + month) : '';
    data = data < 10 ? ('0' + data) : '';
    return year + '-' + month + '-' + data; //強制型別轉換
}
let dt = new Date();
let formtDate = formatDate(dt);
console.log(formatDate())
複製程式碼
  • 獲取隨機數,要求是長度一直的字串格式
let rand = Math.random();
let rand1 = rand + '0000000000';
let rand2 = rand1.slice(0, 10);
console.log(rand2);
複製程式碼

23.png

1.日期

18.png
2.Math (1).獲取隨機數Math.random()。 3.陣列api

19.png

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);
複製程式碼

4.物件api

20.png
總結:

24.png

######8.JS-WEB-API

25.png

26.png

1.DOM操作
(1).獲取DOM節點。
(2). ()()()

複製程式碼

27.png

28.png

29.png

30.png

31.png

32.png

33.png

34.png
######9.BOM

35.png

36.png

37.png

38.png
######10.事件

39.png

40.png

######10.Ajax互動

41.png

42.png

43.png
1.狀態碼

44.png

45.png

46.png

47.png

48.png

49.png

50.png

51.png

52.png

53.png

54.png

######11.儲存

55.png

56.png

57.png

58.png
######12.開發工具

59.png

60.png
######13.模組化

61.png

62.png

63.png

64.png

65.png

66.png

67.png

68.png

69.png

14.前端執行環境
載入資源的形式
載入一個資源的過程
  • 瀏覽器根據DNS伺服器得到域名的IP地址
  • 向這個IP的機器傳送http請求
  • 伺服器收到、處理並返回http請求
  • 瀏覽器得到返回內容
瀏覽器渲染頁面的過程
  • 根據HTML結果生成DOM Tree
  • 根據CSS生成CSSDOM
  • 將DOM和CSSDOM整合形成RenderTree
  • 根據RenderTree開始渲染和展示
  • 遇到時javascript,會執行並阻塞渲染
window.onload 和 DOMContentLoader區別
window.onload : 頁面的全部資源載入完才會執行,包括圖片、視訊等
DOMContentLoader : DOM渲染完即可執行,此時圖片、視訊還沒有載入完
複製程式碼
15.效能優化

1.載入資源優化

  • 靜態資源的壓縮合並
  • 靜態資源快取
  • 使用CDN讓資源載入更快
  • 使用SSR後端渲染,資料直接輸入到HTML中

2.渲染優化

  • css放前面,js放後面
  • 爛載入(圖片懶載入、下拉載入更多)
  • 減少DOM查詢,對DOM查詢做快取
  • 減少DOM操作,多個操作儘量合併在一起執行
  • 事件節流
  • 儘早執行操作(如DOMContentLoaded)
16.安全性

1.XSS跨站請求攻擊

2.XSRF跨站點請求偽造

相關文章