At a cliffhanger!
(Actually… doing some magic tricks)
Let's check out this code.?→
// an empty objectconst hat = {}; // printing out a propertiesconsole.log(hat.toString);// calling a methodconsole.log(hat.toString());
hat
, yet??→[function: toString][object object]
?const hat = {}; console.log(hat.toString); // a functionconsole.log(hat.toString()); // returns object
?All objects have a link to another object that's called its?[[prototype]]
.
[[prototype]]
?means the concept,?prototype?not the actual syntax (confusingly, there are properties and objects in JavaScript that are named?prototype
?but are not exactly the concept?[[prototype]]
)[[prototype]]
?objects have [[prototype]]s as well!null
?prototype is reached / the last object in the chain:?Object.prototype
The top level prototype is?Object.prototype:
Object
Object.prototype
Object.prototype
's [[prototype]] is?null
Let's do some exploring.?→
Object.getPrototypeOf(obj)
obj
…console.log(Object.getPrototypeOf({}) == Object.prototype);
#trueconsole.log(Object.getPrototypeOf(Object.prototype));
#null
?What do you think the [[prototype]] of Array.prototype is?→
console.log(Object.getPrototypeOf(Array.prototype) == Object.prototype);
#true
Object.prototype
?is at the top of the prototype chain (it's the last object checked for properties)toString()
hasOwnProperty()
?(we've seen this before!)Object.create
Object.create
?- creates a new object with the specified [[prototype]] object and properties
// our "template" objectconst protoWerewolf = { description: 'hairy', howl: function(thing) {console.log('The werewolf howls at the ' + thing + '.');}};// make a new werewolf with Object.createconst sadWerewolf = Object.create(protoWerewolf);sadWerewolf.mood = 'sullen';sadWerewolf.howl('moon');
(It turns out, for inheritance, it's common to use Object.create(MyObj.prototype) … we'll see why later)
Another way to create an object with a particular prototype is to use a?constructor.
new
?keyword in front of itnew
this
?object is bound to a?fresh, empty objectnew
?(unless the constructor explicitly returns a different object)In the code below, both?sadWerewolf
?and?partyWerewolf
?are?instances?of?Werewolf
. Note that:
this
?objectthis
?is the object that's returned after calling?new Werewolf
function Werewolf(mood) {this.mood = mood;}const sadWerewolf = new Werewolf('sad'); const partyWerewolf = new Werewolf('partying'); console.log(partyWerewolf.mood);
You can think of the above constructor as doing the following when invoked with new…
function Werewolf(mood) { // this = {}this.mood = mood; // return this}
Let's try adding some more properties to?this
.→
All constructors have a property named?prototype
.
from Object.prototype
Function.prototype
Werewolf.prototype.howl = function(thing) {console.log('The werewolf howls at the ' + thing + '.');}sadWerewolf.howl('moon');partyWerewolf.howl('bowl of chips');
?When we added a property to the constructor's prototype, something unusual happened!??How were the instances of that constructor affected??→
The instances immediately had access to the new property, even though they were instantiated before the prototype was set.
When a property is requested from an object, where are the places that the property is searched for?
Object.prototype
If you add a property directly to an object, it is added to the object?itself, not the object's prototype.?What's the output of the following code??→
Werewolf.prototype.clothing = 'tattered shirt';console.log(partyWerewolf.clothing);partyWerewolf.clothing = 'backwards cap';console.log(partyWerewolf.clothing);console.log(sadWerewolf.clothing);
tattered shirtbackwards captattered shirt
?Again, when you add a property to an object, that property is added to the object itself…
Let's break down all of the properties of our?partyWerewolf
?object and determine where they came from?→
partyWerewolf properties=====
from partyWerewolf object-----clothing: backwards cap mood: partying
from Werewolf.prototype-----clothing: tattered shirt (masked)howl: (function)
from Object-----toString: (function)etc.
?A common pattern for implementing inheritance is to:?→
Object.create
Using our parent constructor,?Werewolf
function Werewolf(mood) { this.mood = mood;}Werewolf.prototype.howl = function(thing) {console.log('The werewolf howls at the ' + thing + '.');}
Create a constructor for a space werewolf (!!!) by setting its prototype to a new object who's prototype is?Werewolf.prototype
function SpaceWerewolf() {}SpaceWerewolf.prototype = Object.create(Werewolf.prototype);
This isn't quite complete, though.?→
A common pattern for implementing inheritance is to:?→
Object.create
Using our parent constructor,?Werewolf
function Werewolf(mood) { this.mood = mood;}Werewolf.prototype.howl = function(thing) {console.log('The werewolf howls at the ' + thing + '.');}
Create a constructor for a space werewolf (!!!) by setting its prototype to a new object who's prototype is?Werewolf.prototype
function SpaceWerewolf() {}SpaceWerewolf.prototype = Object.create(Werewolf.prototype);
This isn't quite complete, though.?→
?In the previous implementation, there's actually some stuff missing when we create a?SpaceWerewolf
. What's missing from the previous implementation that results in incomplete inheritance??→
mood
)?const w = new SpaceWerewolf();console.log(mood)
?Hm. The constructor,?Werewolf
, sets the property,?mood
…
super
?in Java).call
function SpaceWerewolf(mood) { Werewolf.call(this, mood);}
?All object's have a property named?constructor
.?constructor
?is the function that was used to create the instance's prototype.
const a = [];console.log(a.constructor); // [Function: Array]
So we should probably set that on our child constructor's prototype property explicitly so that all objects created from?SpaceWerewolf
?have that as its constructor.
SpaceWerewolf.prototype.constructor = SpaceWerewolf;
function Werewolf(mood) { this.mood = mood;}Werewolf.prototype.howl = function(thing) {console.log('The werewolf howls at the ' + thing + '.');}
function SpaceWerewolf(mood) { Werewolf.call(this, mood);}SpaceWerewolf.prototype = Object.create(Werewolf.prototype);SpaceWerewolf.prototype.constructor = SpaceWerewolf;const w = new SpaceWerewolf('in space');console.log(w.mood);console.log(w.constructor);
?Check out the following example…?→
function Monster() {this.scary = true;}Monster.prototype.boo = function() { console.log('Boo!');}
function Werewolf(mood) { Monster.call(this);this.mood = mood;}Werewolf.prototype = Object.create(Monster.prototype);Werewolf.prototype.constructor = Werewolf;
Werewolf.prototype.howl = function(thing) {console.log('The werewolf howls at the ' + thing + '.');}
?What would the output be if the following code were run…?→
const sadWerewolf = new Werewolf('sad');const partyWerewolf = new Werewolf('partying');partyWerewolf.scary = false;console.log(sadWerewolf.scary);console.log(partyWerewolf.scary);partyWerewolf.boo();
truefalseBoo!
Some notes on the example:
Monster.prototype
?as the prototypeconst sadWerewolf = new Werewolf('sad');?
sadWerewolf
What if we only want the properties that were explicitly set on our object, rather than including inherited ones.?→
We could use the?hasOwnProperty
?method that every object inherits from?Object.prototype
!
console.log('party\n-----');for (const p in partyWerewolf) {if (partyWerewolf.hasOwnProperty(p)) {console.log(p + ': ' + partyWerewolf[p]);}}console.log('\n');console.log('sad\n-----');for (const p in sadWerewolf) {if (sadWerewolf.hasOwnProperty(p)) {console.log(p + ': ' + sadWerewolf[p]);}}
?If you have an object, and you'd like to know what constructor it came from, you can use the?instanceof
?operator.
What do you think the following code will print out??→
console.log(myCar instanceof Car);console.log(myCar instanceof Bike);
truefalse
(in?actuality?instance of checks if an object has in its prototype chain the prototype property of a constructor)
These two bits of code both produce a function called?HttpRequest
!?→
ES6 class:
class HttpRequest {}
ES5 constructor:
function HttpRequest() {}
Both result in the same output when used in the following manner:
const req = new HttpRequest();console.log(HttpRequest);console.log(typeof req.constructor);console.log(req.constructor.name);
?ES6 style classes allow for a constructor to be defined as follows:
this
?which represents the instance that is createdclass HttpRequest { constructor(method, url) { this.method = method; this.url = url; }}
The above code is?mostly?the same as this ES5 function that can be used as a constructor:
function HttpRequest(method, url) { this.method = method; this.url = url;}
We'll see later that subclass constructors must call super before using?this
.
In ES5, to add a method to the prototype, we'd have to do something like this:→
function HttpRequest(method, url) { this.method = method; this.url = url;}
HttpRequest.prototype.makeRequest = function() { return this.method + ' ' + this.url + ' HTTP/1.1';}
?In ES6, we can define methods directly in the class definition, and they will show up in the instances' prototype?→
class HttpRequest { constructor(method, url) { this.method = method; this.url = url; } makeRequest() { return this.method + ' ' + this.url + ' HTTP/1.1'; }}
function
this
, and if the method is called within the context of an instance, then?this
refers to the instanceNote that creating these methods in ES6 style classes is?actually?just adding to the prototype!?→
const req = new HttpRequest('GET', 'http://foo.bar/baz');console.log(req.makeRequest());console.log(Object.getPrototypeOf(req).makeRequest);
?Use?extends
?to inherit from a class!?(read: set up a prototype chain)
class Element { constructor(name) { this.name = name; }}
class ImgElement extends Element { // make sure to call super before using this // within subclass constructor(url) { super('img'); this.url = url; }}
const img = new ImgElement('http://foo.bar/baz.gif');console.log(img.name);console.log(img.url);
?In the previous example,?super
?was used to call the base class constructor.?→
super
?must be called in your subclass constructor if…this
?within your constructorthis
?properties the way that the superclass wouldsuper
?must be called before using this within a subclassEvery object in JavaScript links to another object called its [[prototype]].?→
Object.create
__proto__
?that allows direct access to a [[prototype]], but its use is discouraged)本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...
在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...
在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...
什么是熱更新?熱更新是什么意思?如果您經常玩游戲,您應該會看到,當您打開游戲客戶端時,系統會提示您有更新,您需要下載更新包。對于手機游戲來說,可能從幾米到幾百米不等。對于電腦游戲,如lol,它的范圍也從幾十米到幾百兆字節。這樣,您只需要下載客戶端本身的更新包,而不需要再次下載整個客戶端的更新方法稱為熱更新。蘋果對應用程序和游戲的內容有嚴格的控制。每個應用程序或游戲在上架前都會經過審核。也就是說,蘋...
ip地址顯示異地怎么解決?很有可能是號被盜,接觸把密碼該了,要是我還是跨省登陸賬號。那是很可能主要帶的無線網,首先我要告訴你吧無線網是有追蹤IP的,他會不自動的你把你IP中改其他地方(你在專門買查找IP時,都會顯示是本地,但用上的地方會顯示就會是外地),具體詳細改的地方是無線網重新發行者設置的,通常是而且怕被人修改和使用。QQ登錄時IP地址為啥總在變?畢竟你在其它地方也登陸后過這個號,所有直接登陸...
安徽毫州屬于哪個市 亳州屬于安徽東部嗎?亳州為什么叫亳州? 亳州市位于安徽省北部和安徽省北部。位于安徽省馬鞍山市北部。亳州市是安徽省的地級市,未來宜人宜居。它是中國古代著名醫生華佗的家鄉,也是中國最大的中草藥配送基地。中草藥的年營業額非常大。亳州也是安徽北部重要的交通樞紐,年勞務輸出人口相對較大。 安徽省亳州市屬于哪個市? 安微省毫州市是一個成立于1990年的縣級市,隸屬于蒙城縣、渦陽縣、...