前端筆記——JS基礎(原型&&原型鏈)

weixin_33766168發表於2018-06-14

JavaScript基礎 —— 原型&&原型鏈

建構函式

  function Foo(name, age) {
    this.name = name;
    this.age = age;
    this.class = 'class-1';
    //return this ; //預設有這一行
  }
  var f = new Foo('張三', 22);
  var f1 = new Foo('李四', 29);

建構函式 - 擴充套件

  var a={} 其實是 var a=new Object() 的語法糖
  var a=[] 其實是 var a=new Array() 的語法糖
  function Foo() {....} 其實是 var Foo=new Function(...)
  使用 instanceof 判斷一個函式是否是一個變數的建構函式

原型規則和示例

  • 所有的引用型別(陣列、物件、函式),都具有物件屬性(即可自有擴充套件的屬性),null除外
  • 所有的引用型別(陣列、物件、函式),都有一個 __proto__ 屬性(隱式原型),屬性值是一個普通的物件
  var obj = { };
  obj.x=100;
  console.log(obj.__proto__);
  // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
  var arr = [];
  arr.x = 200;
  console.log(arr.__proto__);
  // [constructor: ƒ, concat: ƒ, find: ƒ, findIndex: ƒ, pop: ƒ, …]
  function fn() {};
  fn.x = 300;
  console.log(fn.__proto__);
  // ƒ () { [native code] }
  var d = null;
  console.log(d.__proto__);
  // Uncaught TypeError: Cannot read property '__proto__' of null
  • 所有的 函式 ,都有一個 prototype 屬性(顯式原型),屬性值也是一個普通物件
  console.log(fn.prototype);
  // {constructor: ƒ}
  • 所有的引用型別(陣列、物件、函式), __proto__ 屬性值指向它的建構函式的 prototype 屬性值
  console.log(obj.__proto__ === Object.prototype);
  // true
  • 當檢視得到一個物件(所有的引用型別)的某個屬性時,如果這個物件本身沒有這個屬性,那麼會去它的 __proto__ (即它的建構函式的 prototype )中尋找。
  // 建構函式
  function Foo(name, age) {
    this.name = name;
  }
  Foo.prototype.alertName = function() {
    console.log('alertName' + this.name);
  }
  // 建立示例
  var f = new Foo('張三');
  f.prientname = function() {
    console.log('prientname' + this.name);
  }
  // 測試
  f.prientname(); // prientname張三
  f.alertName(); // alertName張三

原型鏈

  // 建構函式
  function Foo(name, age) {
    this.name = name;
  }
  Foo.prototype.alertName = function() {
    console.log('alertName' + this.name);
  }
  // 建立示例
  var f = new Foo('張三');
  f.prientname = function() {
    console.log('prientname' + this.name);
  }
  // 測試
  f.prientname(); // prientname張三
  f.alertName(); // alertName張三

  f.toString(); // "[object Object]" 在f.__proto__.__proto__中查詢,即Object的顯式原型中尋找

圖片描述

instanceof

  • instanceof 用於判斷 引用型別 屬於哪個 建構函式 的方法
  // f的 __proto__ 一層一層網上找,找到對應的 Foo.prototype
  f instanceof Foo //true
  f instanceof Object //true

q:如何準確判斷一個變數是陣列型別

  var arr=[]
  // 可以正確判斷的情況
  arr instanceof Array //true
  Object.prototype.toString.call(arr) // "[object Array]"
  Object.prototype.toString.apply(arr) // "[object Array]"
  Array.isArray(arr) // true
  // 不能判斷的情況
  typeof arr // object 是無法判斷是否是陣列的
  // 不準確
  arr.constructor === Array //true 但是原型鏈可以被改寫,這樣判斷不安全
  // 擴充套件 相容老版本瀏覽器,isArray的寫法
  if(!Array.isArray){
    Array.isArray = function(arg){
      return Object.property.toString.call(arg) === '[object Array]'
    }
  }

q:寫一個原型鏈繼承的例子

  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);
    return this;
  }
  var main = new Elem('main')
  main.html('<p>Hello World</p>').on('click', function() {
    alert('Hello javascript')
  })

q:描述 new 一個物件的過程

  • 建立一個物件
  • this 指向這個新物件
  • 執行程式碼,即對 this 賦值
  • 返回 this
  function Foo(name, age) {
    this.name = name;
    this.age = age;
    this.class = 'class-1';
    //return this ; //預設有這一行
  }
  var f = new Foo('張三', 22);
  var f1 = new Foo('李四', 29);

相關文章