分配给对象的Javascript函数无法访问继承的方法

时间:2015-05-06 03:17:46

标签: javascript

毫无疑问,我在这里做了些蠢事,但下面的代码会产生一个

error "this.getString is not a function." 

这是因为当unrelatedInstance调用stringGetter时," this"在showCombinedStrings()中,Unrelated ....的值实际上看起来很公平,但是如何才能设置它以使其有效?

function BaseStringGetter() {
    this.getString = function () {
        return 'this is from BaseStringGetter';    
    }
}

function DerivedStringGetter() {
    this.showCombinedStrings = function () {
        console.log( 'this is from DerivedStringGetter and... ' + this.getString() );
    }
}
DerivedStringGetter.prototype = new BaseStringGetter();
var stringGetterInstance = new DerivedStringGetter();

function Unrelated() {};
var unrelatedInstance = new Unrelated();
unrelatedInstance.stringGetter = stringGetterInstance.showCombinedStrings;
unrelatedInstance.stringGetter();

3 个答案:

答案 0 :(得分:1)

一种选择是:

Sub Send_Unformatted_Rangedata(i As Integer)
Dim noSession As Object, noDatabase As Object, noDocument As Object
Dim vaRecipient As Variant
Dim rnBody As Range
Dim Data As DataObject
Dim rngGen As Range
Dim rngApp As Range
Dim rngspc As Range

Dim stSubject As String
stSubject = "E-Mail For Approval for " + (Sheets("Summary").Cells(i, "A").Value) + "  for the Project  " + Replace(ActiveWorkbook.Name, ".xls", "")
'Const stMsg As String = "Data as part of the e-mail's body."
'Const stPrompt As String = "Please select the range:"

'This is one technique to send an e-mail to many recipients but for larger
'number of recipients it's more convenient to read the recipient-list from
'a range in the workbook.
vaRecipient = VBA.Array(Sheets("Summary").Cells(i, "U").Value, Sheets("Summary").Cells(i, "V").Value)

 On Error Resume Next
'Set rnBody = Application.InputBox(Prompt:=stPrompt, _
     Default:=Selection.Address, Type:=8)
 'The user canceled the operation.
'If rnBody Is Nothing Then Exit Sub
 Set rngGen = Nothing
 Set rngApp = Nothing
 Set rngspc = Nothing

 Set rngGen = Sheets("General Overview").Range("A1:C30").SpecialCells(xlCellTypeVisible)
 Set rngApp = Sheets("Application").Range("A1:E13").SpecialCells(xlCellTypeVisible)

 Set rngspc = Sheets(Sheets("Summary").Cells(i, "P").Value).Range(Sheets("Summary").Cells(i, "Q").Value).SpecialCells(xlCellTypeVisible)
 Set rngspc = Union(rngspc, Sheets(Sheets("Summary").Cells(i, "P").Value).Range(Sheets("Summary").Cells(i, "R").Value).SpecialCells(xlCellTypeVisible))

  On Error GoTo 0

  If rngGen Is Nothing And rngApp Is Nothing And rngspc Is Nothing Then
      MsgBox "The selection is not a range or the sheet is protected. " & _
           vbNewLine & "Please correct and try again.", vbOKOnly
      Exit Sub
  End If

'Instantiate Lotus Notes COM's objects.
Set noSession = CreateObject("Notes.NotesSession")
Set noDatabase = noSession.GETDATABASE("", "")

'Make sure Lotus Notes is open and available.
If noDatabase.IsOpen = False Then noDatabase.OPENMAIL

'Create the document for the e-mail.
Set noDocument = noDatabase.CreateDocument

'Copy the selected range into memory.
rngGen.Copy
rngApp.Copy
rngspc.Copy

'Retrieve the data from then copied range.
Set Data = New DataObject
Data.GetFromClipboard

'Add data to the mainproperties of the e-mail's document.
With noDocument
    .Form = "Memo"
    .SendTo = vaRecipient
    .Subject = stSubject
    'Retrieve the data from the clipboard.
    .Body = Data.GetText & " " & stMsg
    .SaveMessageOnSend = True
End With

'Send the e-mail.
With noDocument
    .PostedDate = Now()
    .send 0, vaRecipient
End With

'Release objects from memory.
Set noDocument = Nothing
Set noDatabase = Nothing
Set noSession = Nothing

'Activate Excel for the user.
'Change Microsoft Excel to Excel
AppActivate "Excel"

'Empty the clipboard.
Application.CutCopyMode = False

MsgBox "The e-mail has successfully been created and distributed.", vbInformation

End Sub

Sub Send_Formatted_Range_Data(i As Integer)
Dim oWorkSpace As Object, oUIDoc As Object
Dim rnBody As Range
Dim lnRetVal As Long
Dim stTo As String
Dim stCC As String
Dim stSubject As String
Const stMsg As String = "An e-mail has been succesfully created and saved."

Dim rngGen As Range
Dim rngApp As Range
Dim rngspc As Range

stTo = Sheets("Summary").Cells(i, "U").Value
stCC = Sheets("Summary").Cells(i, "V").Value
stSubject = "E-Mail For Approval for " + (Sheets("Summary").Cells(i, "A").Value) + "  for the Project  " + Replace(ActiveWorkbook.Name, ".xls", "")

'Check if Lotus Notes is open or not.
lnRetVal = FindWindow("NOTES", vbNullString)

If lnRetVal = 0 Then
    MsgBox "Please make sure that Lotus Notes is open!", vbExclamation
    Exit Sub
End If

Application.ScreenUpdating = False

 Set rngGen = Sheets("General Overview").Range("A1:C30").SpecialCells(xlCellTypeVisible)
 Set rngApp = Sheets("Application").Range("A1:E13").SpecialCells(xlCellTypeVisible)

 Set rngspc = Sheets(Sheets("Summary").Cells(i, "P").Value).Range(Sheets("Summary").Cells(i, "Q").Value).SpecialCells(xlCellTypeVisible)
 Set rngspc = Union(rngspc, Sheets(Sheets("Summary").Cells(i, "P").Value).Range(Sheets("Summary").Cells(i, "R").Value).SpecialCells(xlCellTypeVisible))
 On Error GoTo 0

If rngGen Is Nothing And rngApp Is Nothing And rngspc Is Nothing Then
    MsgBox "The selection is not a range or the sheet is protected. " & _
           vbNewLine & "Please correct and try again.", vbOKOnly
    Exit Sub
End If

rngGen.Copy
rngApp.Copy
rngspc.Copy

'Instantiate the Lotus Notes COM's objects.
Set oWorkSpace = CreateObject("Notes.NotesUIWorkspace")

On Error Resume Next

Set oUIDoc = oWorkSpace.ComposeDocument("", "mail\xldennis.nsf", "Memo")
On Error GoTo 0

Set oUIDoc = oWorkSpace.CurrentDocument

'Using LotusScript to create the e-mail.
Call oUIDoc.FieldSetText("EnterSendTo", stTo)
Call oUIDoc.FieldSetText("EnterCopyTo", stCC)
Call oUIDoc.FieldSetText("Subject", stSubject)

'If You experience any issues with the above three lines then replace it with:
'Call oUIDoc.FieldAppendText("EnterSendTo", stTo)
'Call oUIDoc.FieldAppendText("EnterCopyTo", stCC)
'Call oUIDoc.FieldAppendText("Subject", stSubject)

'The can be used if You want to add a message into the created document.
Call oUIDoc.FieldAppendText("Body", vbNewLine & stBody)

'Here the selected range is pasted into the body of the outgoing e-mail.
Call oUIDoc.GoToField("Body")
Call oUIDoc.Paste

'Save the created document.
Call oUIDoc.Save(True, False, False)
'If the e-mail also should be sent then add the following line.
'Call oUIDoc.Send(True)

'Release objects from memory.
Set oWorkSpace = Nothing
Set oUIDoc = Nothing

With Application
    .CutCopyMode = False
    .ScreenUpdating = True
End With

MsgBox stMsg, vbInformation

'Activate Lotus Notes.
 AppActivate ("Notes")
'Last edited Feb 11, 2015 by Peter Moncera

End Sub

在这里,您使用Function.prototype.bind()unrelatedInstance.stringGetter = stringGetterInstance.showCombinedStrings.bind(stringGetterInstance); unrelatedInstance.stringGetter(); this unrelatedInstance.stringGetter(),并始终返回stringGetterInstance

答案 1 :(得分:0)

当你在一个对象上调用一个函数时,this将引用该函数被调用的对象,即使该函数最初是在别处定义的。

当您致电unrelatedInstance.stringGetter();时,此功能内的this现在会引用unrelatedInstance,但getString()没有unrelatedInstance.stringGetter = function() { return stringGetterInstance.showCombinedStrings(); } MDN this reference page有更多信息。

您可以执行以下操作以保留原始上下文:

bind

编辑:我遗漏了free()其他答案现在已经提到,因为它在IE8中并不存在,但如果你有一个垫片或者不在,那么你可以使用它。关心旧浏览器。

答案 2 :(得分:0)

问题在于您如何致电unrelatedInstance.stringGetter();

尽管stringGetter引用了showCombinedStrings函数,但this内的showCombinedStrings现在指的是unrelatedInstance实例,它没有toString()属性。为什么错误。

演示:Fiddle

此处this的值打印为Unrelated {stringGetter: function},而不是DerivedStringGetter个实例

一个简单的解决方案是使用.bind()为unrelatedInstance.stringGetter提供自定义执行上下文,如

unrelatedInstance.stringGetter = stringGetterInstance.showCombinedStrings.bind(stringGetterInstance);

演示:Fiddle

现在,即使您致电unrelatedInstance.stringGetter()this内的showCombinedStrings也会引用stringGetterInstance个实例。