Javascript:如何访问构造函数的'this'成员? [英] Javascript: how to visit the 'this' member of a construction function?

查看:84
本文介绍了Javascript:如何访问构造函数的'this'成员?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在控制台中,我创建了一个构造函数'Car',如下所示,
和new-ed一个名为'mycar'的对象,它发生如下:

 > var Car = function(){
... this.make =Ford;
...}
undefined

> var mycar = new Car()
undefined

> mycar.make //当我访问mycar.make时,它有效
'Ford'

> Car.make //当我访问Car.make时,它没有工作
undefined

所以我想问:



如何访问'Car.make',就像我访问'mycar.make'一样?


澄清:通过名称 Car 访问 make 但不是通过 mycar


字段在哪里。 make =Ford go?



我还尝试扩展其 __ proto __ in Chrome开发者控制台,但没有找到它。



谢谢!

解决方案

之前



让我们仔细看看下面这段代码:

  Car = function(brand){
this.brand = brand;
}

Car.prototype.getBrand = function(){
return this.brand;
};

福特=新车(福特);
菲亚特=新车(菲亚特);
ford.getBrand(); //Ford
fiat.getBrand(); //菲亚特

乍一看,你可能认为 getBrand ford fiat 所有,但这是错误的。当你想知道事物在内存中的组织方式时,你不应该单独依赖代码,这可能会产生误导。这是一个正确的快照:

  / $ b $b├──Car
│└──原型$ b $b│└──getBrand$ b $b├──ford$ b $b│├──品牌$ b $b│└──__proto__ - > /汽车/原型$ b $b└──fatat$ b $b├──品牌$ b $b└──__proto__ - > / car / prototype

将其视为文件夹结构,其中目录是对象,文件是属性或方法,和链接是对其他对象的引用。正如我所说, / ford / getBrand 不存在。自己检查, ford.hasOwnProperty(getBrand)给出 false 。所以,您可能会问,为什么 ford.getBrand()不会崩溃?这就是名为 __ proto __ 的奇怪东西。



__ proto __ 是一个可以在每个对象中找到的属性。在我们的代码中, / ford / __ proto __ 可以看作是 / Car / prototype 的链接。它也可以被视为一个隐藏文件,因为如果您编写 console.log(ford),您将看不到它。事实是你不应该玩它,使用 __ proto __ 是有争议的,并且已经气馁了。 (详情请参阅 MDN )。



但超出 __ proto __ 争议, ford.getBrand()有效,因为JavaScript实现了所谓的查找机制。当它无法在对象中找到某些东西时,它将继续搜索该对象的原型。碰巧,由于 / ford / getBrand 不存在,JavaScript将查看 / ford / __ proto __



我想告诉你的是,场景背后发生了很多事情,但没有什么神奇之处。该语言执行一些你必须找到和解除的技巧: - )



关于这个



是一个上下文关键字,换句话说,它的值取决于上下文。上下文(=范围)是一组值。例如,全局上下文( / )包含 Car ford fiat ,但它还包含这个,它指的是......全局上下文本身!更有趣的是,JavaScript允许您创建新的上下文。据我所知,调用函数是唯一的方法:

  function f(v){
//上下文出生
// ... ...
//上下文死亡
}
f(); //新的本地上下文
f(); //新的本地上下文

在如上所述的本地上下文中, this 默认情况下指的是全局上下文。你可能想要覆盖默认行为,遗憾的是你不能写 this = anything 。没关系,你仍然可以使用 new 关键字,上下文调用或者......暴力破解这个



默认情况下:

  Car(Ford); 
console.log(品牌);
//打印Ford:-\告诉你,
//在'Car`
/`this`的上下文中指的是全局
//上下文默认为

使用 new 关键字:

  audi = new Car(Audi); 
//在'Car`
//'this`的上下文中指的是`audi`

通过上下文调用:

  ford.getBrand(); //Ford
//在`getBrand`
/`this`的上下文中指的是`ford`

使用暴力:

  ford.getBrand.call(fiat); //Fiat
//在`getBrand`
/`this`的上下文中指的是`fiat`!

然而,正如您所见,永远不会引用 Car ,这就是为什么缺少 / Car / brand 的原因。从构造函数内部向添加属性会修改实例( ford fiat audi ),而不是班级( Car )。



之后



跟踪 ford =新车(福特)

  1。 /车存在吗?是
2.创建一个新对象
3.使用this调用Car =新对象
3.1。将__proto__添加到此
3.2。将此.__ proto__设置为/ Car / prototype
3.1。将品牌添加到
3.2。将this.brand设为​​Ford
3.3。返回此(新对象)
4.将福特设置为新对象

追踪 ford.getBrand.call(fiat)

  1。 /福特存在?是
2. / ford / getBrand存在?没有
3. / ford / __ proto __ / getBrand存在吗?是
4. call / ford / __ proto __ / getBrand with this = fiat
4.1。 /菲特存在?是
4.2。 / fiat /品牌存在?是
4.3。返回/菲亚特/品牌

一个简短的演示:



< pre class =snippet-code-js lang-js prettyprint-override> Car = function(brand){console.log(this === Car =,this === Car); this.brand = brand;} Car.prototype.getBrand = function(){console.log(this === ford =,this === ford); return this.brand;}; ford = new Car(Ford); ford.getBrand(); console.log(ford.hasOwnProperty(\getBrand \)=,ford.hasOwnProperty(getBrand) )); console.log(Car.prototype === ford .__ proto__ =,Car.prototype === ford .__ proto __); console.log(Car =,Car); console.log(ford = ,ford); console.log(Car.prototype =,Car.prototype); console.log(ford .__ proto__ =,ford .__ proto __);


In console, I created a construction function 'Car' like below, and new-ed a object named 'mycar', and it happend like this:

> var Car = function() {
... this.make = "Ford";
... }
undefined

> var mycar = new Car()
undefined

> mycar.make   // when I visit mycar.make, it worked
'Ford'

> Car.make      // when I visit Car.make, it didn't work
undefined

So I want to ask:

how to visit the 'Car.make' like I visit the 'mycar.make'?

clarify: to visit make via the name Car but not via mycar

where did the field this.make="Ford" go?

I also tried to expand its __proto__ in Chrome dev console, but didn't found it.

Thanks!

解决方案

Before this

Let's take a close look at the following piece of code :

Car = function (brand) {
  this.brand = brand;
}

Car.prototype.getBrand = function () {
  return this.brand;
};

ford = new Car("Ford");
fiat = new Car("Fiat");
ford.getBrand(); // "Ford"
fiat.getBrand(); // "Fiat"

At first glance you may think that getBrand is owned by ford and fiat, but it's wrong. When you want to know how things are organized in memory you should not rely on the code alone, it can be misleading. Here is a proper snapshot :

/
├── Car
│   └── prototype
│       └── getBrand
├── ford
│   ├── brand
│   └── __proto__ -> /Car/prototype
└── fiat
    ├── brand
    └── __proto__ -> /Car/prototype

Think of it as a folder structure where directories are objects, files are attributes or methods, and links are references to other objects. As I said, /ford/getBrand doesn't exist. Check by yourself, ford.hasOwnProperty("getBrand") gives false. So, you may ask, why ford.getBrand() doesn't crashes ? This is where this weird stuff called __proto__ comes in.

__proto__ is a property that you can find in every object. In our code, /ford/__proto__ could be seen as a link to /Car/prototype. It could also be seen as a hidden file since you won't see it if you write console.log(ford). The fact is that you are not supposed to play with it, "The use of __proto__ is controversial, and has been discouraged." (read more on this at MDN).

But beyond the __proto__ controversy, ford.getBrand() works because JavaScript implements what's called a lookup mechanism. When it fails to find something into an object, it will keep searching into the prototype of this object. As it happens, since /ford/getBrand does not exist, JavaScript will look into /ford/__proto__.

What I want to show you is that there is a lot of things that happen behind the scene, but there is nothing magical. The language performs some tricks that you have to find and demistify :-)

About this

this is a contextual keyword, in other words, its value depends on a context. A context (= a scope) is a set of values. For example, the global context (/) contains Car, ford and fiat, but it also contains this, which refers to... the global context itself ! More interesting, JavaScript allows you to create new contexts. As far as I know, calling a function is the only way to do it :

function f (v) {
  // context birth
  // ...
  // context death
}
f(); // new local context
f(); // new local context

In a local context like the one above, this refers to the global context by default. You may want to overwrite the default behaviour, unfortunately you can't write this = anything. Nevermind, you can still take control over this using the new keyword, a contextual call or... brute force !

By default :

Car("Ford");
console.log(brand);
// prints "Ford" :-\ told you,
// in the context of `Car`
// `this` refers to the global 
// context by default

With the new keyword :

audi = new Car("Audi");
// in the context of `Car`
// `this` refers to `audi`

With a contextual call :

ford.getBrand(); // "Ford"
// in the context of `getBrand`
// `this` refers to `ford`

Using "brute force" :

ford.getBrand.call(fiat); // "Fiat"
// in the context of `getBrand`
// `this` refers to `fiat` !

However, as you can see, this never refers to Car, that's why /Car/brand is missing. Adding properties to this from the inside of the constructor modifies the instance (ford, fiat or audi), not the class (Car).

After this

Trace of ford = new Car("Ford") :

1. /Car exists ? yes
2. create a new object
3. call Car with this = the new object
  3.1. add __proto__ to this
  3.2. set this.__proto__ to /Car/prototype
  3.1. add brand to this
  3.2. set this.brand to "Ford"
  3.3. return this (the new object)
4. set ford to the new object

Trace of ford.getBrand.call(fiat) :

1. /ford exists ? yes
2. /ford/getBrand exists ? no
3. /ford/__proto__/getBrand exists ? yes
4. call /ford/__proto__/getBrand with this = fiat
  4.1. /fiat exists ? yes
  4.2. /fiat/brand exists ? yes
  4.3. return /fiat/brand

A short demo :

Car = function (brand) {
  console.log("this === Car =", this === Car);
  this.brand = brand;
}

Car.prototype.getBrand = function () {
  console.log("this === ford =", this === ford);
  return this.brand;
};

ford = new Car("Ford");
ford.getBrand();

console.log("ford.hasOwnProperty(\"getBrand\") =", ford.hasOwnProperty("getBrand"));
console.log("Car.prototype === ford.__proto__ =", Car.prototype === ford.__proto__);
console.log("Car =", Car);
console.log("ford =", ford);
console.log("Car.prototype =", Car.prototype);
console.log("ford.__proto__ =", ford.__proto__);

这篇关于Javascript:如何访问构造函数的'this'成员?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆