自定义脚本

概述

SJS(safe/subset javascript)是小程序的一套自定义脚本语言,可以在AXML中使用其构建页面的结构。

使用示例

  • 在.sjs文件中定义 SJS
  1. // /pages/index/index.js
  2. Page({
  3. data: {
  4. msg: 'hello taobao',
  5. },
  6. });
  7. // /pages/xx.sjs
  8. const message = 'hello alipay';
  9. const getMsg = x => x;
  10. export default {
  11. message,
  12. getMsg,
  13. };
  • 在.axml中引用
  1. // /pages/index/index.axml
  2. <!--axml-->
  3. <import-sjs name="m1" from="../xx.sjs"/>
  4. <view>{{m1.message}}</view>
  5. <view>{{m1.getMsg(msg)}}</view>

输出:

  1. hello alipay
  2. hello taobao

注意

  • sjs 只能定义在.sjs文件中。然后在axml中使用import-sjs引入。
  • sjs 可以调用其他 sjs 文件中定义的函数。
  • sjsjavascript 语言的子集,不要将其等同于javascript
  • sjs的运行环境和其他javascript代码是隔离的,sjs中不能调用其他javascript文件中定义的函数,也不能调用小程序提供的API。
  • sjs函数不能作为组件的事件回调。
  • sjs不依赖于运行时的基础库版本,可以在所有版本的小程序中运行。

.sjs

示例代码:

  1. // /pages/hello.sjs
  2. var foo = "'hello alipay' from hello.sjs";
  3. var bar = function(d) {
  4. return d;
  5. };
  6. export default {
  7. foo: foo,
  8. bar: bar
  9. };

上面的例子在/pages/hello.sjs文件中编写了SJS代码。此.sjs文件可以被其他的.sjs文件或者AXML中的<import-sjs>标签引用。

.sjs文件中引用其他.sjs文件

  1. // /pages/message.sjs
  2. import hello from './hello.sjs';
  3. var getMsg = function getMsg(){
  4. return hello + ' message';
  5. }
  6. export default {
  7. getMsg: getMsg
  8. };

axml 中通过 <import-sjs> 标签引入 .sjs模块

  1. <!--/pages/index/index.axml-->
  2. <import-sjs from="../message.sjs" name="m1" />
  3. <view>{{m1.getMsg()}}</view>

页面输出:

  1. hello alipay from hello.sjs message
注意
  • 每一个.sjs文件都是一个独立的模块。
  • 每个模块都有自己独立的作用域。一个模块里面定义的变量与函数,默认为私有的,其他模块不可见。
  • 模块要想对外暴露其内部的私有变量与函数,可通过export default 或者 export {} 实现。
  • 模块如果想要引用另一个模块里面暴露的函数,可以通过import x from './x.sjs'实现

<import-sjs>

属性类型说明
nameString当前<import-sjs>标签的模块名。必填字段。
fromString引用.sjs文件的相对路径。必填字段。
  • name属性是当前<import-sjs>标签的模块名。在单个axml文件内,建议其值唯一。有重复模块名则按照先后顺序覆盖(后者覆盖前者)。不同axml文件之间的sjs模块名不会相互覆盖。
  • name属性可以使用一个字符串表示默认模块名,也可以使用{x}表示命名模块的导出。
  • from属性可以用来引用sjs文件模块。
    引用的时候需要注意以下几点:

  • 只能引用.sjs文件模块,引用时必须加.sjs文件后缀。

  • 如果一个.sjs模块在定义之后,一直没有被引用,则该模块不会被解析与运行。
    示例代码:
  1. // /pages/index/index.js
  2. Page({
  3. data: {
  4. msg: 'hello alipay'
  5. },
  6. });
  1. // /pages/test.sjs
  2. function bar(prefix) {
  3. return prefix;
  4. }
  5. export default {
  6. foo: 'foo',
  7. bar: bar,
  8. };
  1. // /pages/namedExport.sjs
  2. export const x = 3;
  3. export const y = 4;
  1. <!-- /pages/index/index.axml -->
  2. <import-sjs from="../test.sjs" name="test"></import-sjs>
  3. <!-- 也可以直接使用单标签闭合的写法
  4. <import-sjs from="../test.sjs" name="test" />
  5. -->
  6. <!-- 调用 test 模块里面的 bar 函数,且参数为 test 模块里面的 foo -->
  7. <view> {{test.bar(test.foo)}} </view>
  8. <!-- 调用 test 模块里面的 bar 函数,且参数为 page/index/index.js 里面的 msg -->
  9. <view> {{test.bar(msg)}} </view>
  10. <!-- 支持命名导出(named export) -->
  11. <import-sjs from="../namedExport.sjs" name="{x, y: z}" />
  12. <view>{{x}}</view>
  13. <view>{{z}}</view>

页面输出:

  1. foo
  2. hello alipay
  3. 3
  4. 4

上述例子在文件/page/index/index.axml中通过import-sjs标签引用了/page/test.sjs模块。

.sjs语法

变量

示例代码:

  1. var num = 1;
  2. var str = "hello alipay";
  3. var undef; // undef === undefined
  4. const n = 2;
  5. let s = 'string';
注意
  • SJS 中的变量均为值的引用。
  • var 与 javaScript 中表现一致,会有变量提升。
  • 支持 const 与 let。与javascript表现一致。
  • 没有声明的变量直接赋值使用,会被定义为全局变量。
  • 只声明变量而不赋值,默认值为 undefined。
规则

变量命名与javascript规则一致。

注意:以下标识符不能作为变量名

  1. delete
  2. void
  3. typeof
  4. null
  5. undefined
  6. NaN
  7. Infinity
  8. var
  9. if
  10. else
  11. true
  12. false
  13. require
  14. this
  15. function
  16. arguments
  17. return
  18. for
  19. while
  20. do
  21. break
  22. continue
  23. switch
  24. case
  25. default

数据类型

sjs目前支持如下数据类型:

  • string: 字符串
  • boolean: 布尔值
  • number: 数值
  • object: 对象
  • function: 函数
  • array: 数组
  • date: 日期
  • regexp: 正则表达式
判断数据类型

sjs提供了两种判断数据类型的方式:constructor与typeofconstructor示例:

  1. const number = 10;
  2. console.log(number.constructor ); // "Number"
  3. const string = "str";
  4. console.log(string.constructor ); // "String"
  5. const boolean = true;
  6. console.log(boolean.constructor ); // "Boolean"
  7. const object = {};
  8. console.log(object.constructor ); // "Object"
  9. const func = function(){};
  10. console.log(func.constructor ); // "Function"
  11. const array = [];
  12. console.log(array.constructor ); // "Array"
  13. const date = getDate();
  14. console.log(date.constructor ); // "Date"
  15. const regexp = getRegExp();
  16. console.log(regexp.constructor ); // "RegExp"

typeof示例:

  1. const num = 100;
  2. const bool = false;
  3. const obj = {};
  4. const func = function(){};
  5. const array = [];
  6. const date = getDate();
  7. const regexp = getRegExp();
  8. console.log(typeof num ); // 'number'
  9. console.log(typeof bool ); // 'boolean'
  10. console.log(typeof obj ); // 'object'
  11. console.log(typeof func ); // 'function'
  12. console.log(typeof array ); // 'object'
  13. console.log(typeof date ); // 'object'
  14. console.log(typeof regexp ); // 'object'
  15. console.log(typeof undefined ); // 'undefined'
  16. console.log(typeof null ); // 'object'
string

语法:

  1. 'hello alipay';
  2. "hello taobao";

es6语法

  1. // template literal
  2. const a = 'hello';
  3. const str = `${a} alipay`;

属性:

  • constructor: 返回值"String"
  • length
除constructor外属性的具体含义请参考 ES5 标准。

方法:

  • toString
  • valueOf
  • charAt
  • charCodeAt
  • concat
  • indexOf
  • lastIndexOf
  • localeCompare
  • match
  • replace
  • search
  • slice
  • split
  • substring
  • toLowerCase
  • toLocaleLowerCase
  • toUpperCase
  • toLocaleUpperCase
  • trim
具体使用请参考 ES5 标准。
number

语法:

  1. const num = 10;
  2. const PI = 3.141592653589793;

属性:

  • constructor: 返回值"Number"
    方法:

  • toString

  • toLocaleString
  • valueOf
  • toFixed
  • toExponential
  • toPrecision
具体使用请参考 ES5 标准。
boolean

布尔值只有两个特定的值:true 和 false。语法:

  1. const a = true;

属性:

  • constructor: 返回值"Boolean"
    方法:

  • toString

  • valueOf
具体使用请参考 ES5 标准。
object

语法:

  1. var o = {}; //生成一个新的空对象
  2. //生成一个新的非空对象
  3. o = {
  4. 'str' : "str", //object 的 key 可以是字符串
  5. constVar : 2, //object 的 key 也可以是符合变量定义规则的标识符
  6. val : {}, //object 的 value 可以是任何类型
  7. };
  8. //对象属性的读操作
  9. console.log(1 === o['string']);
  10. console.log(2 === o.constVar);
  11. //对象属性的写操作
  12. o['string']++;
  13. o['string'] += 10;
  14. o.constVar++;
  15. o.constVar += 10;
  16. //对象属性的读操作
  17. console.log(12 === o['string']);
  18. console.log(13 === o.constVar);

es6 语法:

  1. //支持
  2. let a = 2;
  3. o = {
  4. a, // object shorthand
  5. b() {}, // object method
  6. };
  7. const { a, b, c: d, e = 'default'} = {a: 1, b: 2, c: 3} // object 解构赋值 & default
  8. const {a, ...other} = {a: 1, b: 2, c: 3}; // object rest
  9. const f = {...others}; // object spread

属性:

  • constructor: 返回值"Object"
  1. console.log("Object" === {a:2,b:"5"}.constructor)

方法:

  • toString:返回字符串 "[object Object]"
function

语法:

  1. //方法 1:函数声明
  2. function a (x) {
  3. return x;
  4. }
  5. //方法 2:函数表达式
  6. var b = function (x) {
  7. return x;
  8. }
  9. //方法 3:箭头函数
  10. const double = x => x * 2;
  11. function f(x = 2){} // argument default
  12. function g({name: n = 'xiaoming', ...other} = {}) {} // 函数参数解构赋值
  13. function h([a, b] = []) {}// 函数参数解构赋值
  14. // 匿名函数、闭包
  15. var c = function (x) {
  16. return function () { return x;}
  17. }
  18. var d = c(25);
  19. console.log( 25 === d() );

argumentsfunction中可以使用arguments关键字。

  1. var a = function(){
  2. console.log(2 === arguments.length);
  3. console.log(1 === arguments[0]);
  4. console.log(2 === arguments[1]);
  5. };
  6. a(1,2);

输出:

  1. true
  2. true
  3. true

属性:

  • constructor: 返回值"Function"
  • length:返回函数的形参个数
    方法:

  • toString:返回字符串 "[function Function]"
    示例:

  1. var f = function (a,b) { }
  2. console.log("Function" === f.constructor);
  3. console.log("[function Function]" === f.toString());
  4. console.log(2 === f.length);

输出:

  1. true
  2. true
  3. true
array

语法:

  1. var a = []; //空数组
  2. a = [5,"5",{},function(){}]; //非空数组,数组元素可以是任何类型
  3. const [b, , c, d = 5] = [1,2,3]; // array解构赋值 & 默认值
  4. const [e, ...other] = [1,2,3]; // array rest
  5. const f = [...other]; //array spread

属性:

  • constructor: 返回值"Array"
  • length
除constructor外属性的具体含义请参考 ES5 标准。

方法:

  • toString
  • concat
  • join
  • pop
  • push
  • reverse
  • shift
  • slice
  • sort
  • splice
  • unshift
  • indexOf
  • lastIndexOf
  • every
  • some
  • forEach
  • map
  • filter
  • reduce
  • reduceRight
具体使用请参考 ES5 标准。
date

语法:生成 date 对象需要使用 getDate函数, 返回一个当前时间的对象。

  1. getDate()
  2. getDate(milliseconds)
  3. getDate(datestring)
  4. getDate(year, month[, date[, hours[, minutes[, seconds[, milliseconds]]]]])

参数:

  • milliseconds: 从1970年1月1日00:00:00 UTC开始计算的毫秒数
  • datestring: 日期字符串,其格式为:"month day, year hours:minutes:seconds"
    示例:
  1. let date = getDate(); //返回当前时间对象
  2. date = getDate(1500000000000);
  3. // Fri Jul 14 2017 10:40:00 GMT+0800 (中国标准时间)
  4. date = getDate('2016-6-29');
  5. // Fri June 29 2016 00:00:00 GMT+0800 (中国标准时间)
  6. date = getDate(2017, 6, 14, 10, 40, 0, 0);
  7. // Fri Jul 14 2017 10:40:00 GMT+0800 (中国标准时间)

属性:

  • constructor: 返回值"Date"
    方法:

  • toString

  • toDateString
  • toTimeString
  • toLocaleString
  • toLocaleDateString
  • toLocaleTimeString
  • valueOf
  • getTime
  • getFullYear
  • getUTCFullYear
  • getMonth
  • getUTCMonth
  • getDate
  • getUTCDate
  • getDay
  • getUTCDay
  • getHours
  • getUTCHours
  • getMinutes
  • getUTCMinutes
  • getSeconds
  • getUTCSeconds
  • getMilliseconds
  • getUTCMilliseconds
  • getTimezoneOffset
  • setTime
  • setMilliseconds
  • setUTCMilliseconds
  • setSeconds
  • setUTCSeconds
  • setMinutes
  • setUTCMinutes
  • setHours
  • setUTCHours
  • setDate
  • setUTCDate
  • setMonth
  • setUTCMonth
  • setFullYear
  • setUTCFullYear
  • toUTCString
  • toISOString
  • toJSON
具体使用请参考 ES5 标准。
regexp

语法:生成 regexp 对象需要使用 getRegExp函数。

  1. getRegExp(pattern[, flags])

参数:

  • pattern: 正则的内容。
  • flags:修饰符。只能包含以下字符:
    • g: global
    • i: ignoreCase
    • m: multiline
      示例:
  1. var reg = getRegExp("name", "img");
  2. console.log("name" === reg.source);
  3. console.log(true === reg.global);
  4. console.log(true === reg.ignoreCase);
  5. console.log(true === reg.multiline);

属性:

  • constructor:返回字符串 "RegExp"
  • global
  • ignoreCase
  • lastIndex
  • multiline
  • source
除constructor外属性的具体含义请参考 ES5 标准。

方法:

  • exec
  • test
  • toString
具体使用请参考 ES5 标准。

注释

注释和 javascript 一致,可以使用如下方法对SJS的代码注释。

  1. // /pages/comment.sjs
  2. // 方法一:这是一个单行注释
  3. /*
  4. 方法二:这是一个多行注释
  5. 中间的内容都会被注释
  6. */
  7. let h = 'hello';
  8. const w = ' alipay';

运算符

算术运算符
  1. const a = 10, b = 20;
  2. console.log(30 === a + b); // 加
  3. console.log(-10 === a - b); //减
  4. console.log(200 === a * b); // 乘
  5. console.log(0.5 === a / b); // 除
  6. console.log(10 === a % b); // 取余
字符串拼接运算符

加法(+)运算符也可以用作字符串拼接,如下:

  1. var a = 'hello' , b = ' alipay';
  2. // 字符串拼接
  3. console.log('hello alipay' === a + b);
比较运算符
  1. var a = 10, b = 20;
  2. console.log(true === (a < b)); // 小于
  3. console.log(false === (a > b)); // 大于
  4. console.log(true === (a <= b)); // 小于等于
  5. console.log(false === (a >= b)); // 大于等于
  6. console.log(false === (a == b)); // 等号
  7. console.log(true === (a != b)); // 非等号
  8. console.log(false === (a === b)); // 全等号
  9. console.log(true === (a !== b)); // 非全等号
逻辑运算符
  1. var a = 10, b = 20;
  2. console.log(20 === (a && b)); // 逻辑与
  3. console.log(10 === (a || b)); // 逻辑或
  4. console.log(false === !a); // 逻辑否,取反运算
位运算符
  1. var a = 10, b = 20;
  2. console.log(80 === (a << 3)); // 左移
  3. console.log(2 === (a >> 2)); // 无符号右移运算
  4. console.log(2 === (a >>> 2)); // 带符号右移运算
  5. console.log(2 === (a & 3)); // 与运算
  6. console.log(9 === (a ^ 3)); // 异或运算
  7. console.log(11 === (a | 3)); // 或运算
赋值运算符
  1. var a = 10;
  2. a = 10; a *= 10;
  3. console.log(100 === a);
  4. a = 10; a /= 5;
  5. console.log(2 === a);
  6. a = 10; a %= 7;
  7. console.log(3 === a);
  8. a = 10; a += 5;
  9. console.log(15 === a);
  10. a = 10; a -= 11;
  11. console.log(-1 === a);
  12. a = 10; a <<= 10;
  13. console.log(10240 === a);
  14. a = 10; a >>= 2;
  15. console.log(2 === a);
  16. a = 10; a >>>= 2;
  17. console.log(2 === a);
  18. a = 10; a &= 3;
  19. console.log(2 === a);
  20. a = 10; a ^= 3;
  21. console.log(9 === a);
  22. a = 10; a |= 3;
  23. console.log(11 === a);
一元运算符
  1. var a = 10, b = 20;
  2. // 自增运算
  3. console.log(10 === a++);
  4. console.log(12 === ++a);
  5. // 自减运算
  6. console.log(12 === a--);
  7. console.log(10 === --a);
  8. // 正值运算
  9. console.log(10 === +a);
  10. // 负值运算
  11. console.log(0-10 === -a);
  12. // 否运算
  13. console.log(-11 === ~a);
  14. // 取反运算
  15. console.log(false === !a);
  16. // delete 运算
  17. console.log(true === delete a.fake);
  18. // void 运算
  19. console.log(undefined === void a);
  20. // typeof 运算
  21. console.log("number" === typeof a);
其他

三元运算符

  1. var a = 10, b = 20;
  2. //条件运算符
  3. console.log(20 === (a >= 10 ? a + 10 : b + 10));

逗号运算符

  1. var a = 10, b = 20;
  2. //逗号运算符
  3. console.log(20 === (a, b));
运算符优先级

SJS 运算符的优先级与 javascript 一致

语句

分支结构
if

示例:

  1. if (a > 1) b = 3;
  2. if (a > 1)
  3. b = 3;
  4. if (a > 1) b = 3;
  5. else b = 4;
  6. if (a > 1)
  7. b = 3;
  8. else
  9. b = 4;
  10. if (a > 1) {
  11. b = 3;
  12. }
  13. if (a > 1) {
  14. b = 3;
  15. } else {
  16. b = 4;
  17. }
  18. if (a > 1) {
  19. b = 3;
  20. } else if (a > 2) {
  21. b = 4;
  22. } else {
  23. b = 6;
  24. }
switch

示例:

  1. var xx = 10;
  2. switch ( xx ) {
  3. case "10":
  4. console.log("string 10");
  5. break;
  6. case 10:
  7. console.log("number 10");
  8. break;
  9. case xx:
  10. console.log("var exp");
  11. break;
  12. default:
  13. console.log("default");
  14. }

输出:

  1. number 10
循环结构
for

示例:

  1. for (var i = 0; i < 9; ++i) {
  2. console.log(i);
  3. if( i >= 2) break;
  4. }

输出:

  1. 0
  2. 1
  3. 2
while

示例:

  1. var i = 0;
  2. while (i < = 1) {
  3. console.log(i);
  4. i++
  5. }
  6. var j = 0;
  7. do {
  8. console.log(j);
  9. j++
  10. } while (j <= 1)

输出:

  1. 0
  2. 1
  3. 0
  4. 1

基础类库

Global

注意:再一次强调,sjs不是javascript,很多全局的属性和方法都是不支持的。

属性:

  • Infinity
  • NaN
  • undefined
具体使用请参考 ES5 标准。

方法:

  • decodeURI
  • decodeURIComponent
  • encodeURI
  • encodeURIComponent
  • isNaN
  • isFinite
  • parseFloat
  • parseInt
具体使用请参考 ES5 标准。
console

console.log 方法可在 console 窗口输出信息。它可以接受多个参数,将它们的结果连接起来输出。

Date

方法:

  • now
  • parse
  • UTC
具体使用请参考 ES5 标准。
Number

属性:

  • MAX_VALUE
  • MIN_VALUE
  • NEGATIVE_INFINITY
  • POSITIVE_INFINITY
具体使用请参考 ES5 标准。
JSON

方法:

  • stringify(object): 将 object 对象转换为 JSON 字符串,并返回该字符串。
  • parse(string): 将 JSON 字符串转化成对象,并返回该对象。
    示例:
  1. console.log(undefined === JSON.stringify());
  2. console.log(undefined === JSON.stringify(undefined));
  3. console.log("null"===JSON.stringify(null));
  4. console.log("222"===JSON.stringify(222));
  5. console.log('"222"'===JSON.stringify("222"));
  6. console.log("true"===JSON.stringify(true));
  7. console.log(undefined===JSON.stringify(function(){}));
  8. console.log(undefined===JSON.parse(JSON.stringify()));
  9. console.log(undefined===JSON.parse(JSON.stringify(undefined)));
  10. console.log(null===JSON.parse(JSON.stringify(null)));
  11. console.log(222===JSON.parse(JSON.stringify(222)));
  12. console.log("222"===JSON.parse(JSON.stringify("222")));
  13. console.log(true===JSON.parse(JSON.stringify(true)));
  14. console.log(undefined===JSON.parse(JSON.stringify(function(){})));
Math

属性:

  • E
  • LN10
  • LN2
  • LOG2E
  • LOG10E
  • PI
  • SQRT1_2
  • SQRT2
具体使用请参考 ES5 标准。

方法:

  • abs
  • acos
  • asin
  • atan
  • atan2
  • ceil
  • cos
  • exp
  • floor
  • log
  • max
  • min
  • pow
  • random
  • round
  • sin
  • sqrt
  • tan
具体使用请参考 ES5 标准。

esnext

sjs 并不是javascript,但是它也支持部分 es6语法。

let & const

语法:

  1. function test(){
  2. let a = 5;
  3. if (true) {
  4. let b = 6;
  5. }
  6. console.log(a); // 5
  7. console.log(b); // ReferenceError: b is not defined
  8. }
箭头函数

语法:

  1. const a = [1,2,3]
  2. const double = x => x * 2; // arrow function expression
  3. console.log(a.map(double))
  4. // Lexical this
  5. var bob = {
  6. _name: "Bob",
  7. _friends: [],
  8. printFriends() {
  9. this._friends.forEach(f =>
  10. console.log(this._name + " knows " + f));
  11. }
  12. };
  13. console.log(bob.printFriends())
更简洁的对象字面量(enhanced object literal)

语法:

  1. var handler = 1;
  2. var obj = {
  3. handler, // object shorthand property
  4. toString() { // 对象方法
  5. return "string";
  6. },
  7. };

注意:

  • 不支持super关键字,不能在对象方法中使用super
模板字符串(template string)

语法:

  1. const h = 'hello';
  2. const msg = `${h} alipay`;
解构赋值(Destructuring)

语法:

  1. // array 解构赋值
  2. var [a, ,b] = [1,2,3];
  3. a === 1;
  4. b === 3;
  5. // object 解构赋值
  6. var { op: a, lhs: { op: b }, rhs: c }
  7. = getASTNode();
  8. // object 解构赋值简写
  9. var {op, lhs, rhs} = getASTNode();
  10. // 函数参数解构赋值
  11. function g({name: x}) {
  12. console.log(x);
  13. }
  14. g({name: 5});
  15. // 解构赋值默认值
  16. var [a = 1] = [];
  17. a === 1;
  18. // 函数参数:解构赋值 + 默认值
  19. function r({x, y, w = 10, h = 10}) {
  20. return x + y + w + h;
  21. }
  22. r({x:1, y:2}) === 23;
Default + Rest + Spread

语法:

  1. // 函数参数默认值
  2. function f(x, y=12) {
  3. // 如果不给y传值,或者传值为undefied,则y的值为12
  4. return x + y;
  5. }
  6. f(3) == 15;
  7. // rest
  8. function f(x, ...y) {
  9. // y是一个数组
  10. return x * y.length;
  11. }
  12. f(3, "hello", true) == 6;
  13. function f(x, y, z) {
  14. return x + y + z;
  15. }
  16. f(...[1,2,3]) == 6; // array spread
  17. const [a, ...b] = [1,2,3]; // array rest, b = [2, 3]
  18. const {c, ...other} = {c: 1, d: 2, e: 3}; // object rest, other = {d: 2, e: 3}
  19. const d = {...other}; // object spread

原文: https://docs.alipay.com/mini/framework/sjs