Javascript:我是否需要为对象中的每个变量设置this.var? 在C++中,我最喜欢的语言,通常声明一个这样的对象: class foo { public: int bar; int getBar() { return bar; } }
调用Javascript:我是否需要为对象中的每个变量设置this.var? 在C++中,我最喜欢的语言,通常声明一个这样的对象: class foo { public: int bar; int getBar() { return bar; } },javascript,scope,this,Javascript,Scope,This,调用getBar()工作正常(忽略bar可能未初始化的事实)。getBar()中的变量bar在类foo的范围内,所以我不需要说this->bar,除非我真的需要明确我指的是类“bar,而不是,比如说,一个参数 现在,我正试图开始使用Javascript中的OOP。因此,我研究了如何定义类,并尝试了同样的方法: function foo() { this.bar = 0; this.getBar = function() { return bar; } } 它给我的条是未定义
getBar()
工作正常(忽略bar
可能未初始化的事实)。getBar()
中的变量bar
在类foo
的范围内,所以我不需要说this->bar
,除非我真的需要明确我指的是类“bar
,而不是,比如说,一个参数
现在,我正试图开始使用Javascript中的OOP。因此,我研究了如何定义类,并尝试了同样的方法:
function foo()
{
this.bar = 0;
this.getBar = function() { return bar; }
}
它给我的条是未定义的
。将bar
更改为this.bar
可以解决此问题,但对每个变量执行此操作会使我的代码非常混乱。这对每个变量都是必要的吗?因为我找不到任何与此相关的问题,这让我觉得我在做一些根本错误的事情
编辑:是的,从评论中我得到的是,
this.bar
,一个对象的属性,引用了一些不同于bar
,一个局部变量的东西。有人能解释一下,在范围和对象方面,这到底是为什么吗?如果有另一种方法来定义一个不需要的对象,JavaScript没有基于类的对象模型。它使用了更强大的原型继承,它可以模仿类,但并不适合。一切都是对象,对象[可以]从其他对象继承
构造函数只是为新创建的对象分配属性的函数。对象(通过调用创建)可以通过(函数的本地)引用
方法也只是一个在对象上调用的函数,同样是this
指向对象。至少当该函数作为对象的属性调用时,使用(点,括号)。这会给新手带来很多困惑,因为如果你传递该函数(例如,传递给事件侦听器),它就会与访问它的对象“分离”
遗产在哪里?“类”的实例继承自同一原型对象。方法被定义为该对象上的函数属性(而不是每个实例一个函数),在其上调用方法的实例只继承该属性
例如:
function Foo() {
this.bar = "foo"; // creating a property on the instance
}
Foo.prototype.foo = 0; // of course you also can define other values to inherit
Foo.prototype.getBar = function() {
// quite useless
return this.bar;
}
var foo = new Foo; // creates an object which inherits from Foo.prototype,
// applies the Foo constructor on it and assigns it to the var
foo.getBar(); // "foo" - the inherited function is applied on the object and
// returns its "bar" property
foo.bar; // "foo" - we could have done this easier.
foo[foo.bar]; // 0 - access the "foo" property, which is inherited
foo.foo = 1; // and now overwrite it by creating an own property of foo
foo[foo.getBar()]; // 1 - gets the overwritten property value. Notice that
(new Foo).foo; // is still 0
所以,我们只使用了那个对象的属性,并且对它很满意。但它们都是“公共的”,可以被覆盖/更改/删除!如果这对你来说无关紧要,那你就幸运了。您可以通过在属性名称前加下划线来表示属性的“私有性”,但这只是对其他开发人员的提示,可能不会遵守(尤其是在错误情况下)
因此,聪明的头脑已经找到了一种解决方案,它使用构造函数作为闭包,允许创建私有的“属性”。javascript函数的每次执行都会为局部变量创建一个新的变量环境,一旦执行完成,这些变量可能会被垃圾收集。在该范围内声明的每个函数也可以访问这些变量,只要这些函数可以被调用(例如,由事件侦听器调用),环境就必须保持不变。因此,通过从构造函数导出本地定义的函数,您可以使用只能由这些函数访问的本地变量来保留变量环境
让我们看看它的实际行动:
function Foo() {
var bar = "foo"; // a local variable
this.getBar = function getter() {
return bar; // accesses the local variable
}; // the assignment to a property makes it available to outside
}
var foo = new Foo; // an object with one method, inheriting from a [currently] empty prototype
foo.getBar(); // "foo" - receives us the value of the "bar" variable in the constructor
这个getter函数是在构造函数中定义的,现在被称为“特权方法”,因为它可以访问“私有”(本地)“属性”(变量)。bar
的值永远不会改变。当然,您也可以为它声明一个setter函数,然后添加一些验证等
请注意,prototype对象上的方法无权访问构造函数的局部变量,但它们可能使用特权方法。让我们添加一个:
Foo.prototype.getFooBar = function() {
return this.getBar() + "bar"; // access the "getBar" function on "this" instance
}
// the inheritance is dynamic, so we can use it on our existing foo object
foo.getFooBar(); // "foobar" - concatenated the "bar" value with a custom suffix
因此,您可以将这两种方法结合起来。请注意,特权方法需要更多内存,因为您使用不同的作用域链(但代码相同)创建不同的函数对象。如果要创建数量惊人的实例,那么应该只在原型上定义方法
当您设置从一个“类”到另一个“类”的继承时,它会变得更复杂一些——基本上,您必须使子原型对象从父原型对象继承,并在子实例上应用父构造函数来创建“私有属性”。看一看,要更接近JavaScript中的OOP,您可能需要看一看模块设计模式(例如,描述) 基于闭包效应,此模式允许模拟对象中的私有属性 对于“private”属性,您可以通过其标识符直接引用它们(即,构造函数中的no
this
关键字)
但是无论如何,JS中的闭包和设计模式是一个高级主题。因此,要熟悉基础知识(也在前面提到的书中进行了解释)。在javascript
中,此
始终指函数的所有者对象。例如,如果在页面中定义函数foo()
,则所有者是javascript对象windows
;或者,如果在html元素
上定义foo()
,则所有者是html元素主体;同样,如果您定义了元素的onclick函数,那么所有者就是锚
在本例中,您在开始时将属性bar
分配给“owner”对象,并尝试返回局部变量bar
由于您从未定义过任何局部变量BEbar
,因此当bar未定义时,它将为您提供帮助
理想情况下,您的代码应该将变量定义为var bar代码>如果要返回值零。明确表示function Person(name) {
this.name = name;
console.log(this); //Developer {language: "js", name: "foo"} if called by Developer
}
function Developer(name, language) {
this.language = language;
Person.call(this, name);
}
var dev = new Developer('foo', 'js');
function foo() {
var bar = 'foobar';
this.getBar = function () {
return bar;
}
}
var f = new foo();
console.log(f.getBar()); //'foobar'
function foo() {
bar = 'foobar';
this.getBar = function () {
return bar;
}
}
var f = new foo();
console.log(window.bar); //'foobar'
function ShoppingCart() {
var items = [];
this.getPrice = function () {
var total = 0;
for (var i = 0; i < items.length; i += 1) {
total += items[i].price;
}
return total;
}
this.addItem = function (item) {
items.push(item);
}
this.checkOut = function () {
var serializedItems = JSON.strigify(items);
//send request to the server...
}
}
var cart = new ShoppingCart();
cart.addItem({ price: 10, type: 'T-shirt' });
cart.addItem({ price: 20, type: 'Pants' });
console.log(cart.getPrice()); //30
var module = (function {
var privateProperty = 42;
function privateMethod() {
console.log('I\'m private');
}
return {
publicMethod: function () {
console.log('I\'m public!');
console.log('I\'ll call a private method!');
privateMethod();
},
publicProperty: 1.68,
getPrivateProperty: function () {
return privateProperty;
},
usePublicProperty: function () {
console.log('I\'ll get a public property...' + this.publicProperty);
}
}
}());
module.privateMethod(); //TypeError
module.publicProperty(); //1.68
module.usePublicProperty(); //I'll get a public property...1.68
module.getPrivateProperty(); //42
module.publicMethod();
/*
* I'm public!
* I'll call a private method!
* I'm private
*/
function Foo() {
this.bar = 0;
this.getBar = function () { return this.bar };
}
var foo = new Foo();
{
bar: 0,
getBar: function () { return this.bar; }
};
var foo = {
bar: 0,
getBar: function () { return this.bar; }
};
function Foo( bar, bob ) {
this.bar = bar;
this.bob = bob;
}
Foo.prototype.calculate = function () {
// 'this' points not to the 'prototype' object
// as you could've expect, but to the objects
// created by calling Foo with the new keyword.
// This is what makes it work.
return this.bar - this.bob;
};
var foo1 = new Foo(9, 5);
var foo2 = new Foo(13, 3);
var result1 = foo1.calculate();
var result2 = foo2.calculate();
console.log(result1); //logs 4
console.log(result2); //logs 10
var x = {};
x.hello = function(){
var k = 'Hello World';
this.m = 'Hello JavaScript';
}
var t = new x.hello();
console.log(t.k); //undefined
console.log(t.m); //Hello JavaScript