JavaScript部分基礎知識回顧(一)

js的數據類型

  • string number boolean undefined null object symbol
  • object中包含了function Array Date

js判斷類型方法

js中判斷類型主要有三種方式,分別爲:typeof instanceof Object.prototype.toString.call()

// typeof
typeof "abc" === "string"  //true 
typeof [] === "array"      //false
typeof function () {} === "function"  //true
//typeof 的返回值有:string, number, boolean, undefined, function, object

//instanceof
[] instanceof Array  //true
"abc" instanceof String  //true

//Object.prototype.toString.call()
Object.prototype.toString.call("abc")  //[object String]

Get請求和Post請求的區別

Get請求:

  • 參數拼接在url上
  • 瀏覽器可以產生緩存
  • 瀏覽器對get請求的url長度有限制
  • 一般用於獲取數據

Post請求:

  • 數據包裝在請求體中發送
  • 一般用於提交表單
  • 要比get安全性高些

閉包

  • 什麼是閉包?
    閉包簡單點說,就是返回一個函數,而這個函數保存了父作用域,此時父作用域不會被清除,此時就形成了一個閉包。閉包的作用很多,比如某些時候需要緩存一個結果,實現一個私有變量等等。
  • 閉包實現的單例模式
const Sington = (function () {
  let instance = null;
  function F() {
    if (instance) return instance;
    instance = this;
  }
  F.getInstance = function () { 
    if (!instance) instance = this;
    return instance; 
  }
  return F;
})();

類的繼承

// 說到繼承,就需要一個基類
function Human(name, age) {
  this.name = name;
  this.age = age;
}
Human.prototype.say = function () {
  console.log(`I am ${this.name}, ${this.age} years old.`);
}
  • 原型鏈繼承
function Man() {
  this.gender = "man";
}
Man.prototype = new Human("a man", 30);
Man.prototype.constructor = Man;
new Man().say();  //I am a man, 30 years old.
new Man().gender;  //man
  • 構造方法繼承
function Woman(name, age) {
  Human.call(this, name, age);
  this.gender = "woman";
}
new Woman("Tina", 26).say();  //此處報錯,因爲構造方法繼承,只是繼承了屬性,而沒有繼承原型上的方法
//所以需要定義say方法
Woman.prototype.say = function () {
  console.log(`I am ${this.name}, ${this.age} years old ${this.gender}.`);
}
new Woman("Tina", 26).say();  //I am Tina, 26 years old woman.
  • 原型鏈和構造方法組合繼承
/** 1.原型鏈繼承
 * 弊:
 *    a.不方便傳遞構造函數參數
 *    b.如果父類中含有引用類型的屬性,則子類實例對其修改會對其他實例有影響
 *    c.子類的原型包含父類的一個實例,有點耗費資源
 * 利:
 *    既能繼承屬性又能繼承原型
 *
 * 2.構造函數繼承
 * 弊:
 *    a.只能繼承屬性,不能繼承原型
 * 利:
 *    方便傳參;不存在引用修改影響問題;不存在浪費資源問題
 */
// 組合繼承,結合兩者優勢,當然也會存在兩者缺陷
function People(name, age) {
  Human.call(this, name, age);
}
People.prototype = new Human();
People.prototype.constructor = People;
new People("Tom", 34).say();  //I am Tom, 34 years old.
  • 寄生繼承
function Personal(name, age) {
  Human.call(this, name, age);
}
(function () {
  function F() {}  //中間宿主
  F.prototype = Human.prototype;
  Personal.prototype = new F();
  Personal.prototype.constructor = Personal;
})();
new Personal("Jet", 99).say();  //I am Jet, 99 years old.

bind,apply,call

/** 三個方法都是改變當前環境中的this指向
 *  call, apply 調用後立即執行,但是參數不一樣,第一個參數都是指定的this,其後的參數都是需要傳遞的參數,call通過逗號分隔,而apply傳入數組
 *  bind 調用後返回一個一個待執行的方法,需要再次主動調用。參數值傳遞只需要指定的那個this
 */
var vn = "window";
function F() {
  this.vn = "F";
}
var f = new F();
function say(name, ex) {
  console.log(name + " say: " + this.vn + " is current this, " + ex);
}
//直接調用
say("Tom", "hahaha");  //Tom say: window is current this, hahaha
// call, apply
say.call(f, "Tom", "hahaha");
say.apply(f, ["Tom", "hahaha"]);
// bind
var say2 = say.bind(f);
say2("Tom", "hahaha");

實現一個深度克隆

var t = {
  a: 1,
  b: [1,2],
  c: [{h: true, i: "abc"}],
  d: {
    x: 1,
    z: function () {}
  },
  e: [1, {a:1}]
}
function copyDeep(obj) {
  var result = obj instanceof Array ? [] : {};
  for (var o in obj) {
    if (obj[o] instanceof Array) {
        result[o] = copyDeep(obj[o]);
    } else if (o instanceof Object) {
        result[o] = copyDeep(obj[o]);
    } else {
        result[o] = obj[o];
    }
  }
  return result;
}

實現一個將原生的ajax封裝成promise

const PromiseAjax = function (url) {
  return new Promise((resolve, rejected) => {
    const httpRequest = new XMLHttpRequest();
    httpRequest.open("GET", url);
    httpRequest.send();
    httpRequest.onreadystatechange = text => {
      if (httpRequest.readyState === 4 && httpRequest.status === 200) {
          //處理成功
          resolve(text);
      }
      if (httpRequest.readyState === 4 && httpRequest.status !== 200) {
          //處理失敗
          rejected(text);
      }
    }
  });
}

實現一個私有變量,用getName方法可以訪問,不能直接訪問

  • Object.defineProperty方式
var test = {
  id: 123,
  name: 'Jaimor'
}
Object.defineProperty(test, 'name', {

});
  • 自定義變量形式
function User(id) {
  this.id = id;
  const name = 'Jaimor';
  this.getName = function () {
    return name;
  }
}
const test = new User(123);
console.log(test.id, test.getName(), test.name);  //123, Jaimor, undefined
  • 閉包方式
const Person = (function () {
  let name = 'Tom';
  return function (id, n) {
    this.id = id;
    name = n;
    this.getName = _ => name
  }
})();

箭頭函數與普通函數的區別

  • 普通函數:有原型,可以通過new創建一個實例,有自己的this綁定。
  • 箭頭函數:
    a) 箭頭函數是匿名函數,不能作爲構造函數,不能使用new。
    b) 箭頭函數不綁定arguments,可以使用...reset
    c) 箭頭函數不綁定this,會捕獲其所在的上下文的this作爲自己的this值,同時call apply bind也不能改變this
    d) 箭頭函數沒有原型屬性。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章