Объем анонимных методов

Просто добавьте радиотэг с меткой при отображении списка

var objectarray=[];//array


function addToArray() {
    //read items from form and create client object
    var clientobject={url};
    //input variables into clientobject

    clientobject.url=document.getElementById("url").value;
    //alert("Client Name: "+clientobject.firstname+" "+clientobject.lastname);
    //load into objectarray
    objectarray.push(clientobject);
    displayList();//display object array

}

function displayList() {
    //variables
    var clientlist="";//this will be the list of elements in the array list
    var displayRadiobuttons="";//display elements as a list of radio buttons

        for (var i=0;i<objectarray.length;i++) 
        {
            //local instance of clientobject
            var clientobject={url};
            clientobject=objectarray[i];
            clientlist= clientobject.url;
            //create radio button tags and elements
            displayRadiobuttons+="<a href=https://"+clientobject.url+" target='_blank'><input type=radio name=listitem ";
            displayRadiobuttons+=" value="+i+" ";
            displayRadiobuttons+=" onchange=deleteItem(this.value)>";
            displayRadiobuttons+=clientlist+"</a><br>";


        }
        //display list
        document.getElementById("showlist").innerHTML=displayRadiobuttons;

}

//delete item from objectarry at index i using splice
function deleteItem(i) {
    //delete ONE  item at index i   
    objectarray.splice(i,1);
    //display modified list
    displayList();
}
<!DOCTYPE html>
<html>
<head>
<title>Track your favorite websites</title>
<meta name="author" content="791894" >
<meta name="date" content="2019-03-01T16:33:43-0700" >
<script type="text/javascript" src="partA.js"></script>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<h2>Please Complete the Following Registration</h2>

<form id="register" onsubmit="addToArray();return false">
<table>

    <tr><td>Enter Your URL Here</td><td><input type="text" id="url" size="25" required="true"></td></tr>

</table>
<input type="submit" value="Submit">
</form>
<h3><span id="showlist"></span></h3>
</body>
</html>

10
задан jpfollenius 30 April 2009 в 08:36
поделиться

4 ответа

Var and out parameters and the Result variable cannot be captured because the safety of this operation cannot be statically verified. When the Result variable is of a managed type, such as a string or an interface, the storage is actually allocated by the caller and a reference to this storage is passed as an implicit parameter; in other words, the Result variable, depending on its type, is just like an out parameter.

The safety cannot be verified for the reason Jon mentioned. The closure created by an anonymous method can outlive the method activation where it was created, and can similarly outlive the activation of the method that called the method where it was created. Thus, any var or out parameters or Result variables captured could end up orphaned, and any writes to them from inside the closure in the future would corrupt the stack.

Of course, Delphi does not run in a managed environment, and it doesn't have the same safety restrictions as e.g. C#. The language could let you do what you want. However, it would result in hard to diagnose bugs in situations where it went wrong. The bad behaviour would manifest itself as local variables in a routine changing value with no visible proximate cause; it would be even worse if the method reference were called from another thread.

This would be fairly hard to debug. Even hardware memory breakpoints would be a relatively poor tool, as the stack is modified frequently. One would need to turn on the hardware memory breakpoints conditionally upon hitting another breakpoint (e.g. upon method entry). The Delphi debugger can do this, but I would hazard a guess that most people don't know about the technique.

Update: With respect to the additions to your question, the semantics of passing instance references by value is little different between methods that contain a closure (and capture the paramete0 and methods that don't contain a closure. Either method may retain a reference to the argument passed by value; methods not capturing the parameter may simply add the reference to a list, or store it in a private field.

The situation is different with parameters passed by reference because the expectations of the caller are different. A programmer doing this:

procedure GetSomeString(out s: string);
// ...
GetSomeString(s);

would be extremely surprised if GetSomeString were to keep a reference to the s variable passed in. On the other hand:

procedure AddObject(obj: TObject);
// ...
AddObject(TObject.Create);

It is not surprising that AddObject keeps a reference, since the very name implies that it's adding the parameter to some stateful store. Whether that stateful store is in the form of a closure or not is an implementation detail of the AddObject method.

20
ответ дан 3 December 2019 в 15:06
поделиться

Я помещаю это в отдельный ответ, потому что ваш EDIT делает ваш вопрос действительно другим.

Я, вероятно, расширю этот ответ позже, так как я немного спешу добраться до клиента.

Ваша правка указывает на то, что вам необходимо переосмыслить типы значений, ссылочные типы и влияние разметки var, out, const и отсутствия параметров.

Давайте сначала разберемся с типами значений.

Значения типов значений находятся в стеке и имеют функцию копирования при назначении. (Я постараюсь привести пример позже).

Если у вас нет маркировки параметра, фактическое значение, переданное методу (процедуре или функции), будет скопировано в локальное значение этого параметра внутри метода. Таким образом, метод работает не со значением, переданным ему, а с копией.

Когда вы используете out, var или const, копирование не происходит: метод будет ссылаться на фактическое переданное значение. Для var это позволит изменить это фактическое значение, для const это не допустит. Иными словами, вы не сможете прочитать фактическое значение, но все равно сможете записать фактическое значение.

Значения ссылочных типов живут в куче, поэтому для них это вряд ли имеет значение, если вы вышли, var, константная или нулевая маркировка параметров: когда вы что-то меняете, вы меняете значение в куче.

Для ссылочных типов: (Барри, вероятно, может объяснить это даже лучше, но я попробую) В вашем отредактированном случае анонимный метод будет захватывать локальную копию списка. Анонимный метод будет работать с этой локальной копией, и с точки зрения компилятора все будет просто замечательно.

Однако суть вашего редактирования - это сочетание «оно работает для нормальных параметров» и «который гарантирует, что ссылка все еще указывает». к живому объекту всякий раз, когда выполняется анонимный метод ».

Это всегда проблема со ссылочными параметрами, независимо от того, используете ли вы анонимные методы или нет.

Например, это:

procedure TMyClass.AddObject(Value: TObject);
begin
  FValue := Value;
end;

procedure TMyClass.DoSomething();
begin
  ShowMessage(FValue.ToString());
end;

Кто гарантирует это, когда кто-то вызывает Что-то, что экземпляр, на который указывает FValue, все еще существует? Ответ заключается в том, что вы должны гарантировать это сами, не вызывая DoSomething после смерти экземпляра FValue. То же самое относится и к вашему редактированию: вы не должны вызывать анонимный метод, когда базовый экземпляр умер.

Это одна из областей, где подсчет ссылок или сборка мусора облегчают жизнь: там экземпляр будет поддерживаться до тех пор, пока последняя ссылка на него ушла (что может привести к тому, что экземпляр будет жить дольше, чем вы изначально ожидали!).

Таким образом, с вашим редактированием ваш вопрос фактически меняется с анонимных методов на последствия использования ссылочных типизированных параметров и управления временем жизни в генерал.

Надеюсь, мой ответ поможет вам в этом.

- Йерун

0
ответ дан 3 December 2019 в 15:06
поделиться

The out parameter and return value are irrelevant after the function returns - how would you expect the anonymous method to behave if you captured it and executed it later? (In particular, if you use the anonymous method to create a delegate but never execute it, the out parameter and return value wouldn't be set by the time the function returned.)

Out parameters are particularly difficult - the variable that the out parameter aliases may not even exist by the time you later call the delegate. For example, suppose you were able to capture the out parameter and return the anonymous method, but the out parameter is a local variable in the calling function, and it's on the stack. If the calling method then returned after storing the delegate somewhere (or returning it) what would happen when the delegate was finally called? Where would it write to when the out parameter's value was set?

4
ответ дан 3 December 2019 в 15:06
поделиться

The problem is that your Str1 variable is not "owned" by ReturnTwoStrings, so that your anonymous method cannot capture it.

The reason it cannot capture it, is that the compiler does not know the ultimate owner (somewhere in the call stack towards calling ReturnTwoStrings) so it cannot determine where to capture it from.

Edit: (Added after a comment of Smasher)

The core of anonymous methods is that they capture the variables (not their values).

Allen Bauer (CodeGear) explains a bit more about variable capturing in his blog.

There is a C# question about circumventing your problem as well.

6
ответ дан 3 December 2019 в 15:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: