- 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/
只有 3 行代码,但我无法完全理解这一点: Object.create = function (o) { function F() {} F.prototype = o; re
我知道有很多关于“Javascript:好的部分”的问题和文档,但我试图理解书中一句话的意思,但不太明白。在第 41-42 页中,他定义了 serial_maker 函数: var serial_ma
这是什么意思: "When a function object is created, the Function constructor that produces the function obje
下面的代码几乎与道格拉斯·克罗克福德 (Douglas Crockford) 的精湛著作《JavaScript:好的部分》第 29-30 页中的一些代码相同。唯一的区别是他像这样添加了 get_sta
出于兴趣,我想学习如何为一种简单的语言编写解析器,并最终为我自己的代码打高尔夫球语言编写解释器,一旦我了解了这些东西的一般工作原理。 所以我开始阅读 Douglas Crockfords 的文章 To
最近我看了一个 Douglas Crockford 的演讲(他的演讲让我着迷,但总是让我感到困惑)。他举了一个构造函数的例子,但我不太明白我将如何在实践中使用它: function construct
我正在尝试使用 Crockford 的继承模式构建基类 Shape。使用这个基本形状,我试图画一个圆、一个矩形和一个三 Angular 形。我有点卡住了。我不知道如何调用/修改基本方法 functio
我刚读完 The Good Parts,我对某事有点困惑。 Crockford 的伪经典继承示例如下: var Mammal = function (name) { this.name = n
希望有人能帮我分解 Crockford 的 JS Good Parts 中的一段代码: Function.method('new', function ( ) { // Create a new
在函数式继承模式中,Crockford 引入了一个新的superior 方法: Object.method('superior', function (name) { var that = t
我刚刚看了 Douglas Crockford 的视频,他给出了以下练习: write a function, that when passed a variable, returns a funct
我观看了 YUIConf 2012 的视频,其中 Douglas Crockford 发表了关于在 JavaScript 中实现 monad 的演讲。在本次演讲中,他给出了一个代码示例,该示例使用了他
在接下来的文章中,Douglas Crockford 创建了一个函数来更接近地模拟 JavaScript 中的原型(prototype)继承 (http://javascript.crockford.
在 Douglas Crockford 的 JavaScript: The Good Parts 中,他用这段代码解释了伪经典继承的思想,其中显示 Cat 继承自 Mammal. var Cat =
/** Supplant **/ String.prototype.supplant = function(o) { return this.replace (/{([^{}]*)}/g,
在 Javascript the good parts 一书中,Ch3 on objects 的开篇,它指出: An object is a container of properties, wher
我最近尝试为一个经常创建的值对象优化一些代码。 (三维向量,fwiw) 我尝试的一件事是将构造函数从匿名方法工厂模式转换为普通的 JavaScript 构造函数。 这导致了 severe perfor
只是在 JS 中尝试不同的继承技术,并且发现了一些关于 Crockford 的原型(prototype)继承模式的稍微令人不安的事情: function object(o) { functio
在 Douglas Crockford 的文章中,Private Members in Javascript ,他使用变量“that”来引用“this”,以便在类的特权方法中使用。我一直在我的代码中使
https://github.com/douglascrockford/JSON-js/blob/master/json_parse.js在此链接中,Douglas Crockford 创建了一个 j
我是一名优秀的程序员,十分优秀!