javascript 面向對象 new 關鍵字 原型鏈 構造函數

JavaScript面向對象
JavaScript 語言使用構造函數(constructor)做爲對象的模板。所謂」構造函數」,就是專門用來生成實例對象的函數。它就是對象的模板,描述實例對象的基本結構。一個構造函數,能夠生成多個實例對象,這些實例對象都有相同的結構javascript

  1. 構造函數的首字母大寫,區分通常函數。
  2. 函數體內部使用了this關鍵字,表明了所要生成的對象實例。
  3. 生成對象的時候,必須使用new命令。
  4. 構造函數內部使用嚴格模式 'use strict',防止當作通常函數調用,這樣就會報錯。
function Person(name, age, sex) {
    'use strict';
    this.name = name;
    this.age = age;
    this.sex = sex;
}

Person() 報錯
new Person("zhangxc", 29, "male");

一、new關鍵字 命令內部實現java

function _new(constructor, params) { // 接受個數不肯定參數,第一個參數:構造函數;第二個到第n個參數:構造函數傳遞的參數。
    // 1. 首先將參數組成一個數組 
    // 首先 .slice 這個方法在不接受任何參數的時候會返回 this 自己,這是一個 Array.prototype 下的方法,所以 this 就是指向調用 .slice 方法的數組自己。
    var args = Array.prototype.slice.call(arguments); // arguments僞數組,獲取函數的全部參數的僞數組。
    // 等價於
    // [].slice.call(arguments);
    // 2. 獲取構造函數
    var constructor = args.shift(); // shift()返回數組第一個元素
    // 3. 使用構造函數原型建立一個對象。咱們但願以這個現有的對象做爲模板,生成新的實例對象,這時就可使用Object.create()方法。
    var context = Object.create(constructor.prototype); // Object.create()參數是一個對象,新建的對象繼承參數對象的全部屬性
    // 4. 將參數屬性附加到對象上面
    var result = constructor.apply(context, args);
    // 5. 返回一個對象
    return (typeof result === 'object' && result != null) ? result : context;
}

function Person(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
}

var args1 = _new(Person, "zhangxc", 18, "male");

// {name: "zhangxc", age: 18, sex: "male"}

var args2 = new Person("zhangxc", 18, "male");

// {name: "zhangxc", age: 18, sex: "male"}

new.target屬性git

若是當前函數是new命令調用,new.target指向當前函數(構造函數的名稱),不然爲undefined。github

function Test() {
  console.log(new.target === Test);
}

Test() // false
new Test() // true

二、this關鍵字
this老是指向調用該方法的對象,在最外面調用就指向window
bind, call, apply均可以改變this的指向數組

var name = "window";
var obj = {
    name: "object"
}
function fun() {
    console.log(this.name);
}

一、直接調用 fun() // window 
由於此時fun() this指向window對象

二、fun.call(obj);    // "object" 
call改變了this的指向,此時this指向obj對象,this.name 在obj對象裏面取值,而不是window對象了。

詳細講解鏈接:https://github.com/mqyqingfen...app

三、對象的繼承
JavaScript 語言的繼承不經過 class,而是經過「原型對象」(prototype)實現。函數

prototype原型對象ui

  1. 每個函數都有一個原型對象
  2. 每個實例對象都有一個 __proto__屬性

JavaScript 繼承機制的設計思想就是,原型對象的全部屬性和方法,都能被實例對象共享。也就是說,若是屬性和方法定義在原型上,那麼全部實例對象就能共享,不只節省了內存,還體現了實例對象之間的聯繫。原型對象的做用,就是定義全部實例對象共享的屬性和方法。這也是它被稱爲原型對象的緣由,而實例對象能夠視做從原型對象衍生出來的子對象。this

// 定義水果構造函數
function Fruit(name, color) {
    this.name = name;
    this.color = color;
}

// 實例化apple對象
var apple = new Fruit("apple", "red");

// 實例化banana 對象
var banana = new Fruit("banana", "yellow");

// 若是他們有共同的屬性和方法那麼就使用 prototype
// 修改 Fruit構造函數
Fruit.prototype.address = "china";
Fruit.prototype.eat = function() {
    console.log(this.name + "-----" + this.color);
}

apple.addess // china
banana.address // china

apple.eat()  // apple ---- red
banana.eat() // banana ---- yellow


function M1() {
  this.hello = 'hello';
}

function M2() {
  this.world = 'world';
}

**// 一、繼承M1,M2本身的屬性和方法(hasOwnProperty)**
function S() {
  M1.call(this);
  M2.call(this);
}

**// 二、繼承M1原型鏈上的屬性和方法**
S.prototype = Object.create(M1.prototype);
**// 三、繼承M2原型鏈上的屬性和方法**
Object.assign(S.prototype, M2.prototype);

// 指定構造函數
S.prototype.constructor = S;

var s = new S();
s.hello // 'hello'
s.world // 'world'

四、原型鏈
最透徹的原型鏈講解 哈哈prototype

**1. 每個函數都有prototype屬性指向他的原型對象**
**2. 每個對象都有__proto__屬性指向他的原型對象**

而後以Date()時間 構造函數爲例講解
證實:

var data = new Date();
由於:
data是一個實例對象因此他有__proto__屬性指向他的原型對象
Date是一個構造函數因此他有prototype屬性指向他的原型對象
因此:Date.prototype == data.__proto__    // Date{} true
data.__proto__是一個對象
由於:javascript規定全部對象都有原型
因此: data.__proto__.__proto__  == Object.prototype // true
這就是原型鏈了 data.__proto__.__proto__
data對象繼承了 Date Object 原型對象的屬性和方法。
相關文章
相關標籤/搜索