关于dapp合约中方法调用时call关键字的问题

孙老师,你好,     我看到课程里面合约调用中有时加了call如下面的totalvoteFor,而voteForCandidate又不用加call关键字有点不理解,这个call关键字的作用是什么?
> contractInstance.totalVotesFor.call('Rama')
{ [String: '0'] s: 1, e: 0, c: [ 0 ] }
> contractInstance.voteForCandidate('Rama', {from: web3.eth.accounts[0]})
'0xdedc7ae544c3dde74ab5a0b07422c5a51b5240603d31074f5b75c0ebc786bf53'
> contractInstance.voteForCandidate('Rama', {from: web3.eth.accounts[0]})
'0x02c054d238038d68b65d55770fabfca592a5cf6590229ab91bbe7cd72da46de9'
> contractInstance.voteForCandidate('Rama', {from: web3.eth.accounts[0]})
'0x3da069a09577514f2baaa11bc3015a16edf26aad28dffbcd126bde2e71f2b76f'
> contractInstance.totalVotesFor.call('Rama').toString()
发现调用totalvoteFor时候不加call也行, 但是voteForCandidate后面加了call就不行。  

孙善禄

赞同来自: fish dudu2014

这个问题主要是要理解call的作用,请先阅读下面的代码示例,以及他们的区别:
// Automatically determines the use of call or sendTransaction based on the method type
myContractInstance.myMethod(param1 [, param2, ...] [, transactionObject] [, defaultBlock] [, callback]);

// Explicitly calling this method
myContractInstance.myMethod.call(param1 [, param2, ...] [, transactionObject] [, defaultBlock] [, callback]);

// Explicitly sending a transaction to this method
myContractInstance.myMethod.sendTransaction(param1 [, param2, ...] [, transactionObject] [, callback]);

// Get the call data, so you can call the contract through some other means
var myCallData = myContractInstance.myMethod.getData(param1 [, param2, ...]);
// myCallData = '0x45ff3ff6000000000004545345345345..'
从示例的解释可以看到,myContractInstance.myMethod.call() 是直接调用myMethod方法;当不显示使用call时候,myContractInstance.myMethod()会自动根据方法type调用call或者sendTransaction方法。 sendTransaction方法是需要额外给出发起人账户的‘from’,因此你提到的调用voteForCandidate方法时候,后面加call不可以,那是因为此时自动适配调用的是voteForCandidate.sendTransaction()方法,因此你可以尝试显示调用:contractInstance.voteForCandidate.sendTransaction('Rama', {from:web3.eth.accou nts[0]}) 跟contractInstance.voteForCandidate('Rama', {from:web3.eth.accou nts[0]})是一样的。   另外,关于call 还有额外的用法,供参考:https://solidity.readthedocs.io/en/latest/types.html#address  
address nameReg = 0x72ba7d8e73fe8eb666ea66babc8116a41bfb10e2;
nameReg.call("register", "MyName");
nameReg.call(bytes4(keccak256("fun(uint256)")), a);

要回复问题请先登录注册