js學習日記-new Object和Object.create到底幹了啥

function Car () {
    this.color = "red";
}
Car.prototype.sayHi=function(){
  console.log('你好')
}
var car =new Car(); var car2 = Object.create(Car);

new XXX()時發生了什麼?

var obj={};
obj.__proto=Car.prototype
Car.call(obj)

第一步,建立了一個空對象obj
第二步,將空對象的__proto__成員指向了Car函數的原型屬性,該原型屬性是一個原型對象,也就意味着obj的原型屬性上擁有了Car.prototype中的屬性或方法javascript

第三步,將Car函數中的this指針指向obj,obj有了Car構造函數中的屬性或方法 ,而後Car函數無返回值或返回的不是對象,直接返回obj,不然返回Car函數中的對象java


 

tip:__proto__是什麼瀏覽器

每一個對象都有一個[[prototype]}屬性,這個屬性是隱藏屬性,誰建立了它,該屬性就指向誰的prototype屬性,由於是隱藏屬性,不能直接訪問,因此有的瀏覽器提供了一個__proto__屬性來訪問,然而這不是一個標準的訪問方法,因此ES5中用Object.getPrototypeOf函數得到一個對象的[[prototype]]。ES6中,使用Object.setPrototypeOf能夠直接修改一個對象的[[prototype]]函數

Object.create時發生了什麼?

Object.create()方法建立一個新對象,並使用現有的對象來提供新建立的對象的__proto__,關鍵代碼以下this

關鍵代碼以下:prototype

Object.create =  function (o) {
    var F = function () {};
    F.prototype = o;
    var newObj=new F();
    return newObj;
};

能夠看到Object.create內部建立了一個新對象newObj,默認狀況下newObj.__proto__== F.prototype,在本例中則重寫了構造函數F的原型屬性,最終的原型關係鏈爲newObj.__proto__== F.prototype == o指針

若是現有的對象是一個構造函數,即var car2=Object.create(Car)會發生什麼呢?code

console.log(car2.color)    //undefined
console.log(car2.sayHi())  //undefined

執行代碼發現都是undefined, 爲何會這樣呢?對象

問題1:由於Object.create內部的新對象是new F()建立的,跟Car構造函數沒有半毛錢的關係,因此天然不能訪問到Car中的屬性了blog

問題2:調用car2.sayHi()時首先判斷car2對象有沒有相應的方法,若是沒有,則查找car2的原型鏈上有沒有該方法,car2的原型屬性是Car構造函數(能夠經過car2.__proto__來證實),構造函數沒有sayHi方法,天然也就是undefined了。

那若是將var car2=Object.create(car)又發生了什麼呢?

function Car () {
    this.color = "red";
    this.person={name:'張三'}
}
Car.prototype.sayHi=function(){
  console.log('你好')
}
var car =new Car();
var car2 =  Object.create(car);
car2.person.name ='李四'
console.log(`car是${car.person.name},car2是${car2.person.name}`)

至關於實現了原型繼承方式(注意不是原型鏈繼承),本質上來講是對一個對象進行了淺拷貝  


最終結論:

1. Object.create(o),若是o是一個構造函數,則採用這種方法來建立對像沒有意義

2.Object.create(o),若是o是一個字面量對象或實例對象,那麼至關因而實現了對象的淺拷貝

相關文章
相關標籤/搜索