- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在一次名为“前进之路”的演讲中,道格拉斯·克罗克福德(Douglass Crockford)表示他不再在JavaScript中使用"new",而是逐渐摆脱了“这个”。他说JavaScript的好功能不是原型(prototype)继承,而是无类继承。他提供了以下代码片段,这是他定义对象的方式:
function constructor(init) {
var that = other_constructor(init),
member,
method = function () {
// init, member, method
};
that.method = method;
return that;
}
他解释说:
I've got a function which will take some value to initialize it. I recommend that to be an object, (that way you can have a JSON text you can use to create new instances). You can call another constructor if you want to inherit it's stuff; in any case, you're going to create an object and put it in a variable called "that". You will create all of your member variables (things that are going to become properties of the object, of your method variables, things that are going to act on the object...) those methods will be functions which will close over the initialization value over all the member variables and all the method variables.
It could also use "this" and "that", but I recommend not. The reason for not doing that is, if it doesn't use "this" or "that", then you can take any of the functions out of the object and call them independantly and they still do exactly the same thing. So that increases the reliability of the language. Also means you can pass any of those things, use it as a call back without having to bind anything (It just becomes more reliable). Then any methods that need to be public or privilaged you simply attach them to the object and return the object. This is a really flexible pattern-- you can get multiple inheritance, you can get aspects, you can get factories-- lots of things you can do with this basic pattern.
that.method = method
方法有什么目的?如何初始化?以这种方式声明对象的目的是什么?
最佳答案
Why does this snippet make the following assignment?
that.method = method
what purpose does
method
serve? How is it initialized?
method = function () { ... }
然后,您引用的那一行将变量的值(对该函数的引用)分配给
that
所引用的对象的属性,因此可以将其用作对象的“方法”。因此,您可以这样做:
var x = constructor(42);
x.method(); // <== Here's where we use the function assigned to the property as a method
更多(在我的博客上):
Mythical methods
What is the purpose of declaring objects in this way?
new
关键字。但是我也很喜欢在它们不是正确的工具时就不必使用它们,而通常它们并不是正确的工具。
Would you by any chance be able to provide an example of Crockford's constructor function snippet in actual use? Is that.method used to initialize that.member, or am I totally off here?
that.member
。您显示的代码中的
member
不是对象的属性,而只是一个变量。在对
method
的调用中创建的
constructor
函数可以访问该变量,因为它是对
constructor
的调用上下文的封闭,但是只有有权访问返回对象的对象才能看到
member
。因此,
member
真正是
constructor
中创建的函数的专用。另外两篇文章可能在这里有用:我博客中的
Closures are not complicated解释了什么是“关闭”,以及克罗克福德的
Private Members in JavaScript,它描述了将私有(private)信息与他引用的示例中使用的对象相关联的方式。 (我在回答的最后提到了一种不同的方式来获取有关对象的私有(private)信息。)
// Very simple Crockford-style constructor
function createThing(name) {
return {name: name}; // Again, there'd probably be more to it, this is simple on purpose
}
// Usage
var t = createThing("foo");
console.log(t.name); // "foo"
到现在为止还挺好。现在,我们还希望能够创建可以添加计数器的事物,以及一种“使用”事物和使用计数的方法,以返回新的使用计数。 (是的,这个
是一个人为的示例。)一个简单的版本,再次使用类似于Crockford的方法,可能看起来像这样:
// Naive approach
function createThingWithCounter(name) {
var that = createThing(name);
that.useCounter = 0;
that.use = function() {
// ...do something with `that`...
// Return the new number of times we've "used" the thing
return ++that.useCounter;
};
return that;
}
// Usage
var t = createThingWithCounter("foo");
console.log(t.name); // "foo"
console.log(t.use()); // 1
console.log(t.use()); // 2
再次,到目前为止一切顺利。但是问题是,
useCounter
是对象的公共(public)属性。因此,我们可以从
createThingWithCounter
代码之外对其进行处理:
var t = createThingWithCounter("foo");
console.log(t.name); // "foo"
console.log(t.use()); // 1
t.useCounter = 0;
console.log(t.use()); // 1 -- uh oh!
我们不希望
useCounter
公开。现在,有多种方法可以将其设为私有(private),包括根本不使其私有(private)化,而是使用命名约定(通常以下划线开头,例如
_useCounter
),意思是“别管它了!”,但是这种模式通过查看,我们可以利用
useCounter
方法是对
use
的调用上下文的封闭,从而使
createThingWithCounter
真正私有(private)。这样,再加上一些重新布置源代码以更好地适应引用的模式,可以为我们提供以下功能:
function createThingWithCounter(name) {
var that = createThing(name),
useCounter = 0,
use = function() {
// ...do something with `that`...
// Return the new number of times we've "used" the thing
return ++useCounter;
};
that.use = use;
return that;
}
现在,
useCounter
根本不是对象的属性。它是真正的私有(private),
createThingWithCounter
之外的任何人都看不到或更改它:
var t = createThingWithCounter("foo");
console.log(t.name); // "foo"
console.log(t.use()); // 1
t.useCounter = 0; // <== Has absolutely no effect on the real counter
console.log(t.use()); // 2
这就是我们的具体示例(如果有人为)。它是如何映射到引用的模式的:
constructor
= createThingWithCounter
otherConstructor
= createThing
member
= useCounter
method
= use
new
的普通构造函数来完成的。它看起来甚至没有什么不同:
// Doing the same thing with normal constructor functions and `new`
function Thing(name) {
this.name = name;
}
// Usage
var t = new Thing("foo");
console.log(t.name); // "foo"
// Augmented things
function ThingWithCounter(name) {
var useCounter = 0;
Thing.call(this, name);
this.use = function() {
// ...do something with `this`...
// Return the new number of times we've "used" the thing
return ++useCounter;
};
}
// Usage of augmented things
var t = new ThingWithCounter("foo");
console.log(t.name); // "foo"
console.log(t.use()); // 1
t.useCounter = 0; // <== Has absolutely no effect on the real counter
console.log(t.use()); // 2
它们只是达成相似目标的不同方式。
useCounter
都是真正的私有(private),但它不是对象的属性。它根本不在对象上。获得隐私的方式有很多成本:首先,我们必须为每个实例创建一个
use
函数。这些功能不会在实例之间共享,例如可以附加到原型(prototype)的功能(以及其他各种方式)可以共享。 2014年的成本相当低廉,现代引擎在优化成本方面非常聪明; 15年前,它的成本要高得多。
use
函数无法在其他地方重用,这使其与JavaScript中的绝大多数函数不符。如果查看
the spec,则几乎在每个预定义的JavaScript方法上都会看到此语言:
NOTE: The xyz function is intentionally generic; it does not require that its this value be a Whatsit object. Therefore it can be transferred to other kinds of objects for use as a method.
arguments
对象),则可以将
Array.prototype
中的方法放在上面,并且只要我的对象足够像数组,它们就可以正常工作:
var arrayLikeObject = {
length: 2,
0: "one",
1: "two",
indexOf: Array.prototype.indexOf
};
console.log(arrayLikeObject.indexOf("two")); // 1
我们的
use
方法不能以这种方式重复使用。它被锁定在与之相关的“带有计数器的事物”实例上。如果我们确实尝试过以这种方式使用它,我们最终将在我们要放入的对象与我们原来使用的带有计数器的对象之间发生奇怪的串扰。这种奇怪的串扰是
很棒的很好的方式,可以在任何规模的项目中都有真正令人讨厌,费时,笨拙的错误。
use
函数作为闭包,我们可以在原型(prototype)对象上定义它和/或在其他对象上重用它-也就是说,这两个成本都没有以上适用。
关于javascript - 我不了解Crockford的JavaScript:前进的道路,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24248426/
我正在制作一个基于网格的游戏。 在这个游戏中,您可以放置建筑物、墙壁和道路。 当某些东西被放置在网格中时,我将单元格 ID 设置为该对象 ID。到目前为止一切顺利,一切正常。 当我需要时,我的问题
我想创建一个交互式 map ,其中道路等的样式为我想要的颜色。现在,我了解了 Mapbox,但这不是我们想要使用的,因为最终它会因为费用而花费我们很多钱。 我一直在互联网上寻找替代方案。我发现了很多拼
我正在尝试用 Java 制作一个正则表达式,它可以粗略地用于匹配某些街道名称。我想这样做,以便给定以下字符串: Then someone decided to go to the high stree
尝试用颜色“标记”一个区域并在该区域放置一个数字: 我在这里说明了它: 数字是静态的,不会改变。 区域标记假设会改变颜色。并且区域标记假设使用周围的街道/道路包围该区域(不仅仅是简单的圆形图) 我会尝
我需要能够使用 V2 或 V3(最好是 3)创建在某种意义上忽略建筑物的路径。 我什至试图创建一个 kml 文件来自己绘制所有路径,然后找到一些方法根据需要打开/关闭它们。 例如。用户想从 A 点到
我在 http://www.41latitude.com/post/1268734799/google-styled-maps 上找到了一个代码片段: [ { featureType: "
我正在使用 Roads Google API 传递一个位置列表,我想根据这些点在最有可能由汽车行驶的道路上画线。 有些地方出了问题,因为有些点没有被线穿过,而且这些线不仅仅使用道路,有些点通过直线穿过
我们如何使用切换按钮在 Mapbox gl js 中突出显示(更改颜色)道路、人行道或自行车道? 最佳答案 您可以使用setPaintProperty更改图层的填充颜色,就像在官方 Mapbox 示例
我正在尝试在道路上绘制一条路径并遵循一些给定的点。我正在使用 Google Directions API 来遵循道路。我在道路上放置了一些标记并将这些点与折线连接起来。我需要遵循红线但是它跟随并绘制蓝
我是一名优秀的程序员,十分优秀!