美文网首页
5 函数、事件与修改器

5 函数、事件与修改器

作者: 智能合约大师兄 | 来源:发表于2019-11-21 10:15 被阅读0次

和其它常见的编程语言一样在solidity中函数是一个重要的功能组成部分,外部账户和合约之间、合约与合约之间的交互实际上都是通过函数来完成的。函数体实现包括我们常见的参数列表与返回值,也支持调用其它内部函数、继承来的函数以及递归调用等,但由于栈高度上限为1024所以循环次数、函数调用深度等不能太深,较深的递归可以用循环替代。由于区块链平台编程的特殊性,solidity在传统的函数概念上叠加了区块链相关的特性比如支付属性、修改器和fallback陷进函数等。函数正式的文法定义如下:

ModifierDefinition = 'modifier' Identifier ParameterList? Block
ModifierInvocation = Identifier ( '(' ExpressionList? ')' )?

FunctionDefinition = 'function' Identifier? ParameterList
                     ( ModifierInvocation | StateMutability | 
                    'external' | 'public' | 'internal' | 'private' )*
                     ( 'returns' ParameterList )? ( ';' | Block )
                     
Block = '{' Statement* '}'
Statement = IfStatement | WhileStatement | ForStatement | Block |                   InlineAssemblyStatement | ( DoWhileStatement | 
        PlaceholderStatement | Continue | Break | Return | 
        Throw | EmitStatement | SimpleStatement ) ‘;'

从函数文法定义可知solidity中函数以关键字function开头,然后跟函数名称和参数列表,后面跟修改器列表和可见性说明符。函数修改器也支持多个参数和自己的函数体。最后是返回值列表其中返回值和参数列表一样支持多个。后面跟函数体或者空函数体,而函数体也就是我们前面介绍的顺序、分支和循环语句的组合或嵌套。有一点需要注意的是函数头中返回值列表定义时是returns关键字而在进行实际值返回时是return关键字,这点在实际使用时需特别注意。下面我们详细介绍函数的每一个组成部分的功能特性和注意事项。

5.1 函数参数

solidity中函数支持2种类型的入口参数:与函数定义时数量和类型一致的参数列表和命名参数列表,示意代码如下:

contract ArgsTest {
    function argsGet(address target, uint amount) public view returns(uint) {
        uint total = target.balance + amount;
        return total;
    }

    function doTest() public view returns(uint, uint, uint){
        uint uptAmt = 123;
        uint total1 = argsGet(msg.sender, uptAmt);
        uint total2 = argsGet({target:msg.sender, amount:uptAmt});
        uint total3 = argsGet({amount:uptAmt, target:msg.sender});
        return (total1, total2, total3);
    }
}

由范例代码可知当使用默认参数传递方式时,参数类型和数量必须与定义时一致。但使用命名参数传递时顺序可以任意指定但数量要一致,这三种调用方式返回结果都是一样的,结果如下:

{
    "0": "uint256: 99999999999996843958",
    "1": "uint256: 99999999999996843958",
    "2": "uint256: 99999999999996843958"
}

笔者建议尽可能使用命名参数传递方式提高程序可读性降低潜在的由于参数传递位置错误导致的程序错误。参数在函数体内没有使用时可以省略其名称,示意代码如下:

function argsIgnore(uint amount, bytes4) public pure returns(uint) {
        return amount + 10;
}

实例中我们只用到了第一个参数amount而没有用第二个参数,所以可以忽略其名称。忽略函数参数列表中变量名称的实现在接口合约函数定义、事件定义以及继承中比较常见。

另外需要注意的是数组作为参数传递时需要明确指定存储位置。当以memory方式拷贝传递,因此函数体内的修改不会影响原值,但如果明确指定通过storage方式进行传递则传递的是引用,函数体内的修改会影响原值,示意代码如下:

contract ArgsTest2 {
    uint[] datas;
    event LogVal(string info, uint first, uint second);
    function arrayMem(uint[] memory arr) public pure{
        arr[0] = 333; arr[1] = 444;
    }
    function arrayStorage(uint[] storage arr) internal {
        arr[0] = 333; arr[1] = 444;
    }

    function doTest() public {
        datas = new uint[](2);
        datas[0] = 11; datas[1]=22;

        emit LogVal("before arrayDefault", datas[0], datas[1]);
        arrayMem(datas);
        emit LogVal("after arrayDefault", datas[0], datas[1]);
        
        emit LogVal("before arrayStorage", datas[0], datas[1]);
        arrayStorage(datas);
        emit LogVal("after arrayStorage", datas[0], datas[1]);
    }
}

笔者建议如无特殊原因在将数组作为参数传递给函数时明确指定其存储位置如memory。

5.2 函数返回值

相关文章

  • 5 函数、事件与修改器

    和其它常见的编程语言一样在solidity中函数是一个重要的功能组成部分,外部账户和合约之间、合约与合约之间的交互...

  • 【Solidity智能合约系列】10--函数修改器

    函数修改器(Function Modifiers) 函数修改器(Modifiers)可以用来改变一个函数的行为。比...

  • solidity基础(4)

    solidity的函数修改器函数修改器可以方便的控制函数的逻辑,比如可以在某个行为执行前检查某个前置条件,函数修改...

  • Python JavaScript2: 函数

    总体内容1、函数的定义与调用2、提取行间事件与匿名函数3、网页换肤4、变量和函数的域解析5、函数传参与return...

  • HTML事件学习

    1.掌握什么是事件2.HTML事件3.DOM0级事件4.常用的鼠标与键盘事件 5.this指向问题在事件触发函数中...

  • js函数条件

    函数定义与执行 变量与函数预解析 提取行间事件 匿名函数 函数传参 作业

  • xp粒子插件入个门

    1、control控制类:改粒子组: 颜色修改器: 粒子冻结: 历史修改器: 比如过了5秒,让粒子改变方向; 继承...

  • 学习vue2.0笔记(第三章下)

    事件绑定:v-on:click="event"缩写@click="aaaa"提供默认的修改器 :比如: v-on:...

  • CrossFilter修改器函数

  • JS事件

    事件是可以被 JavaScript 侦测到的行为 事件通常与函数配合使用,当事件发生时函数才会执行 onload ...

网友评论

      本文标题:5 函数、事件与修改器

      本文链接:https://www.haomeiwen.com/subject/qzcbictx.html