自定义脚本
概述
SJS(safe/subset javascript)
是小程序的一套自定义脚本语言,可以在AXML
中使用其构建页面的结构。
使用示例
- 在.sjs文件中定义 SJS
// /pages/index/index.js
Page({
data: {
msg: 'hello taobao',
},
});
// /pages/xx.sjs
const message = 'hello alipay';
const getMsg = x => x;
export default {
message,
getMsg,
};
- 在.axml中引用
// /pages/index/index.axml
<!--axml-->
<import-sjs name="m1" from="../xx.sjs"/>
<view>{{m1.message}}</view>
<view>{{m1.getMsg(msg)}}</view>
输出:
hello alipay
hello taobao
注意
sjs
只能定义在.sjs
文件中。然后在axml
中使用import-sjs
引入。sjs
可以调用其他sjs
文件中定义的函数。sjs
是javascript
语言的子集,不要将其等同于javascript
。sjs
的运行环境和其他javascript
代码是隔离的,sjs
中不能调用其他javascript
文件中定义的函数,也不能调用小程序提供的API。sjs
函数不能作为组件的事件回调。sjs
不依赖于运行时的基础库版本,可以在所有版本的小程序中运行。
.sjs
示例代码:
// /pages/hello.sjs
var foo = "'hello alipay' from hello.sjs";
var bar = function(d) {
return d;
};
export default {
foo: foo,
bar: bar
};
上面的例子在/pages/hello.sjs
文件中编写了SJS
代码。此.sjs
文件可以被其他的.sjs
文件或者AXML
中的<import-sjs>
标签引用。
.sjs文件中引用其他.sjs文件
// /pages/message.sjs
import hello from './hello.sjs';
var getMsg = function getMsg(){
return hello + ' message';
}
export default {
getMsg: getMsg
};
axml 中通过 <import-sjs>
标签引入 .sjs模块
<!--/pages/index/index.axml-->
<import-sjs from="../message.sjs" name="m1" />
<view>{{m1.getMsg()}}</view>
页面输出:
hello alipay from hello.sjs message
注意
- 每一个
.sjs
文件都是一个独立的模块。 - 每个模块都有自己独立的作用域。一个模块里面定义的变量与函数,默认为私有的,其他模块不可见。
- 模块要想对外暴露其内部的私有变量与函数,可通过export default 或者 export {} 实现。
- 模块如果想要引用另一个模块里面暴露的函数,可以通过import x from './x.sjs'实现
<import-sjs>
属性 | 类型 | 说明 |
---|---|---|
name | String | 当前<import-sjs> 标签的模块名。必填字段。 |
from | String | 引用.sjs 文件的相对路径。必填字段。 |
name
属性是当前<import-sjs>
标签的模块名。在单个axml
文件内,建议其值唯一。有重复模块名则按照先后顺序覆盖(后者覆盖前者)。不同axml
文件之间的sjs
模块名不会相互覆盖。name
属性可以使用一个字符串表示默认模块名,也可以使用{x}
表示命名模块的导出。from
属性可以用来引用sjs
文件模块。
引用的时候需要注意以下几点:只能引用
.sjs
文件模块,引用时必须加.sjs
文件后缀。- 如果一个
.sjs
模块在定义之后,一直没有被引用,则该模块不会被解析与运行。
示例代码:
// /pages/index/index.js
Page({
data: {
msg: 'hello alipay'
},
});
// /pages/test.sjs
function bar(prefix) {
return prefix;
}
export default {
foo: 'foo',
bar: bar,
};
// /pages/namedExport.sjs
export const x = 3;
export const y = 4;
<!-- /pages/index/index.axml -->
<import-sjs from="../test.sjs" name="test"></import-sjs>
<!-- 也可以直接使用单标签闭合的写法
<import-sjs from="../test.sjs" name="test" />
-->
<!-- 调用 test 模块里面的 bar 函数,且参数为 test 模块里面的 foo -->
<view> {{test.bar(test.foo)}} </view>
<!-- 调用 test 模块里面的 bar 函数,且参数为 page/index/index.js 里面的 msg -->
<view> {{test.bar(msg)}} </view>
<!-- 支持命名导出(named export) -->
<import-sjs from="../namedExport.sjs" name="{x, y: z}" />
<view>{{x}}</view>
<view>{{z}}</view>
页面输出:
foo
hello alipay
3
4
上述例子在文件/page/index/index.axml
中通过import-sjs
标签引用了/page/test.sjs
模块。
.sjs语法
变量
示例代码:
var num = 1;
var str = "hello alipay";
var undef; // undef === undefined
const n = 2;
let s = 'string';
注意
- SJS 中的变量均为值的引用。
- var 与 javaScript 中表现一致,会有变量提升。
- 支持 const 与 let。与javascript表现一致。
- 没有声明的变量直接赋值使用,会被定义为全局变量。
- 只声明变量而不赋值,默认值为 undefined。
规则
变量命名与javascript规则一致。
注意:以下标识符不能作为变量名
delete
void
typeof
null
undefined
NaN
Infinity
var
if
else
true
false
require
this
function
arguments
return
for
while
do
break
continue
switch
case
default
数据类型
sjs目前支持如下数据类型:
string
: 字符串boolean
: 布尔值number
: 数值object
: 对象function
: 函数array
: 数组date
: 日期regexp
: 正则表达式
判断数据类型
sjs提供了两种判断数据类型的方式:constructor与typeofconstructor示例:
const number = 10;
console.log(number.constructor ); // "Number"
const string = "str";
console.log(string.constructor ); // "String"
const boolean = true;
console.log(boolean.constructor ); // "Boolean"
const object = {};
console.log(object.constructor ); // "Object"
const func = function(){};
console.log(func.constructor ); // "Function"
const array = [];
console.log(array.constructor ); // "Array"
const date = getDate();
console.log(date.constructor ); // "Date"
const regexp = getRegExp();
console.log(regexp.constructor ); // "RegExp"
typeof示例:
const num = 100;
const bool = false;
const obj = {};
const func = function(){};
const array = [];
const date = getDate();
const regexp = getRegExp();
console.log(typeof num ); // 'number'
console.log(typeof bool ); // 'boolean'
console.log(typeof obj ); // 'object'
console.log(typeof func ); // 'function'
console.log(typeof array ); // 'object'
console.log(typeof date ); // 'object'
console.log(typeof regexp ); // 'object'
console.log(typeof undefined ); // 'undefined'
console.log(typeof null ); // 'object'
string
语法:
'hello alipay';
"hello taobao";
es6语法
// template literal
const a = 'hello';
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
语法:
const num = 10;
const PI = 3.141592653589793;
属性:
constructor
: 返回值"Number"
方法:toString
- toLocaleString
- valueOf
- toFixed
- toExponential
- toPrecision
具体使用请参考 ES5 标准。
boolean
布尔值只有两个特定的值:true 和 false。语法:
const a = true;
属性:
constructor
: 返回值"Boolean"
方法:toString
- valueOf
具体使用请参考 ES5 标准。
object
语法:
var o = {}; //生成一个新的空对象
//生成一个新的非空对象
o = {
'str' : "str", //object 的 key 可以是字符串
constVar : 2, //object 的 key 也可以是符合变量定义规则的标识符
val : {}, //object 的 value 可以是任何类型
};
//对象属性的读操作
console.log(1 === o['string']);
console.log(2 === o.constVar);
//对象属性的写操作
o['string']++;
o['string'] += 10;
o.constVar++;
o.constVar += 10;
//对象属性的读操作
console.log(12 === o['string']);
console.log(13 === o.constVar);
es6 语法:
//支持
let a = 2;
o = {
a, // object shorthand
b() {}, // object method
};
const { a, b, c: d, e = 'default'} = {a: 1, b: 2, c: 3} // object 解构赋值 & default
const {a, ...other} = {a: 1, b: 2, c: 3}; // object rest
const f = {...others}; // object spread
属性:
constructor
: 返回值"Object"
console.log("Object" === {a:2,b:"5"}.constructor)
方法:
- toString:返回字符串
"[object Object]"
。
function
语法:
//方法 1:函数声明
function a (x) {
return x;
}
//方法 2:函数表达式
var b = function (x) {
return x;
}
//方法 3:箭头函数
const double = x => x * 2;
function f(x = 2){} // argument default
function g({name: n = 'xiaoming', ...other} = {}) {} // 函数参数解构赋值
function h([a, b] = []) {}// 函数参数解构赋值
// 匿名函数、闭包
var c = function (x) {
return function () { return x;}
}
var d = c(25);
console.log( 25 === d() );
argumentsfunction中可以使用arguments
关键字。
var a = function(){
console.log(2 === arguments.length);
console.log(1 === arguments[0]);
console.log(2 === arguments[1]);
};
a(1,2);
输出:
true
true
true
属性:
constructor
: 返回值"Function"
length
:返回函数的形参个数
方法:toString:返回字符串
"[function Function]"
。
示例:
var f = function (a,b) { }
console.log("Function" === f.constructor);
console.log("[function Function]" === f.toString());
console.log(2 === f.length);
输出:
true
true
true
array
语法:
var a = []; //空数组
a = [5,"5",{},function(){}]; //非空数组,数组元素可以是任何类型
const [b, , c, d = 5] = [1,2,3]; // array解构赋值 & 默认值
const [e, ...other] = [1,2,3]; // array rest
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函数, 返回一个当前时间的对象。
getDate()
getDate(milliseconds)
getDate(datestring)
getDate(year, month[, date[, hours[, minutes[, seconds[, milliseconds]]]]])
参数:
milliseconds
: 从1970年1月1日00:00:00 UTC开始计算的毫秒数datestring
: 日期字符串,其格式为:"month day, year hoursseconds"
示例:
let date = getDate(); //返回当前时间对象
date = getDate(1500000000000);
// Fri Jul 14 2017 10:40:00 GMT+0800 (中国标准时间)
date = getDate('2016-6-29');
// Fri June 29 2016 00:00:00 GMT+0800 (中国标准时间)
date = getDate(2017, 6, 14, 10, 40, 0, 0);
// 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函数。
getRegExp(pattern[, flags])
参数:
- pattern: 正则的内容。
- flags:修饰符。只能包含以下字符:
g
: globali
: ignoreCasem
: multiline
示例:
var reg = getRegExp("name", "img");
console.log("name" === reg.source);
console.log(true === reg.global);
console.log(true === reg.ignoreCase);
console.log(true === reg.multiline);
属性:
- constructor:返回字符串
"RegExp"
。 - global
- ignoreCase
- lastIndex
- multiline
- source
除constructor外属性的具体含义请参考 ES5 标准。
方法:
- exec
- test
- toString
具体使用请参考 ES5 标准。
注释
注释和 javascript 一致,可以使用如下方法对SJS的代码注释。
// /pages/comment.sjs
// 方法一:这是一个单行注释
/*
方法二:这是一个多行注释
中间的内容都会被注释
*/
let h = 'hello';
const w = ' alipay';
运算符
算术运算符
const a = 10, b = 20;
console.log(30 === a + b); // 加
console.log(-10 === a - b); //减
console.log(200 === a * b); // 乘
console.log(0.5 === a / b); // 除
console.log(10 === a % b); // 取余
字符串拼接运算符
加法(+
)运算符也可以用作字符串拼接,如下:
var a = 'hello' , b = ' alipay';
// 字符串拼接
console.log('hello alipay' === a + b);
比较运算符
var a = 10, b = 20;
console.log(true === (a < b)); // 小于
console.log(false === (a > b)); // 大于
console.log(true === (a <= b)); // 小于等于
console.log(false === (a >= b)); // 大于等于
console.log(false === (a == b)); // 等号
console.log(true === (a != b)); // 非等号
console.log(false === (a === b)); // 全等号
console.log(true === (a !== b)); // 非全等号
逻辑运算符
var a = 10, b = 20;
console.log(20 === (a && b)); // 逻辑与
console.log(10 === (a || b)); // 逻辑或
console.log(false === !a); // 逻辑否,取反运算
位运算符
var a = 10, b = 20;
console.log(80 === (a << 3)); // 左移
console.log(2 === (a >> 2)); // 无符号右移运算
console.log(2 === (a >>> 2)); // 带符号右移运算
console.log(2 === (a & 3)); // 与运算
console.log(9 === (a ^ 3)); // 异或运算
console.log(11 === (a | 3)); // 或运算
赋值运算符
var a = 10;
a = 10; a *= 10;
console.log(100 === a);
a = 10; a /= 5;
console.log(2 === a);
a = 10; a %= 7;
console.log(3 === a);
a = 10; a += 5;
console.log(15 === a);
a = 10; a -= 11;
console.log(-1 === a);
a = 10; a <<= 10;
console.log(10240 === a);
a = 10; a >>= 2;
console.log(2 === a);
a = 10; a >>>= 2;
console.log(2 === a);
a = 10; a &= 3;
console.log(2 === a);
a = 10; a ^= 3;
console.log(9 === a);
a = 10; a |= 3;
console.log(11 === a);
一元运算符
var a = 10, b = 20;
// 自增运算
console.log(10 === a++);
console.log(12 === ++a);
// 自减运算
console.log(12 === a--);
console.log(10 === --a);
// 正值运算
console.log(10 === +a);
// 负值运算
console.log(0-10 === -a);
// 否运算
console.log(-11 === ~a);
// 取反运算
console.log(false === !a);
// delete 运算
console.log(true === delete a.fake);
// void 运算
console.log(undefined === void a);
// typeof 运算
console.log("number" === typeof a);
其他
三元运算符
var a = 10, b = 20;
//条件运算符
console.log(20 === (a >= 10 ? a + 10 : b + 10));
逗号运算符
var a = 10, b = 20;
//逗号运算符
console.log(20 === (a, b));
运算符优先级
SJS 运算符的优先级与 javascript 一致
语句
分支结构
if
示例:
if (a > 1) b = 3;
if (a > 1)
b = 3;
if (a > 1) b = 3;
else b = 4;
if (a > 1)
b = 3;
else
b = 4;
if (a > 1) {
b = 3;
}
if (a > 1) {
b = 3;
} else {
b = 4;
}
if (a > 1) {
b = 3;
} else if (a > 2) {
b = 4;
} else {
b = 6;
}
switch
示例:
var xx = 10;
switch ( xx ) {
case "10":
console.log("string 10");
break;
case 10:
console.log("number 10");
break;
case xx:
console.log("var exp");
break;
default:
console.log("default");
}
输出:
number 10
循环结构
for
示例:
for (var i = 0; i < 9; ++i) {
console.log(i);
if( i >= 2) break;
}
输出:
0
1
2
while
示例:
var i = 0;
while (i < = 1) {
console.log(i);
i++
}
var j = 0;
do {
console.log(j);
j++
} while (j <= 1)
输出:
0
1
0
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 字符串转化成对象,并返回该对象。
示例:
console.log(undefined === JSON.stringify());
console.log(undefined === JSON.stringify(undefined));
console.log("null"===JSON.stringify(null));
console.log("222"===JSON.stringify(222));
console.log('"222"'===JSON.stringify("222"));
console.log("true"===JSON.stringify(true));
console.log(undefined===JSON.stringify(function(){}));
console.log(undefined===JSON.parse(JSON.stringify()));
console.log(undefined===JSON.parse(JSON.stringify(undefined)));
console.log(null===JSON.parse(JSON.stringify(null)));
console.log(222===JSON.parse(JSON.stringify(222)));
console.log("222"===JSON.parse(JSON.stringify("222")));
console.log(true===JSON.parse(JSON.stringify(true)));
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
语法:
function test(){
let a = 5;
if (true) {
let b = 6;
}
console.log(a); // 5
console.log(b); // ReferenceError: b is not defined
}
箭头函数
语法:
const a = [1,2,3]
const double = x => x * 2; // arrow function expression
console.log(a.map(double))
// Lexical this
var bob = {
_name: "Bob",
_friends: [],
printFriends() {
this._friends.forEach(f =>
console.log(this._name + " knows " + f));
}
};
console.log(bob.printFriends())
更简洁的对象字面量(enhanced object literal)
语法:
var handler = 1;
var obj = {
handler, // object shorthand property
toString() { // 对象方法
return "string";
},
};
注意:
- 不支持
super
关键字,不能在对象方法中使用super
模板字符串(template string)
语法:
const h = 'hello';
const msg = `${h} alipay`;
解构赋值(Destructuring)
语法:
// array 解构赋值
var [a, ,b] = [1,2,3];
a === 1;
b === 3;
// object 解构赋值
var { op: a, lhs: { op: b }, rhs: c }
= getASTNode();
// object 解构赋值简写
var {op, lhs, rhs} = getASTNode();
// 函数参数解构赋值
function g({name: x}) {
console.log(x);
}
g({name: 5});
// 解构赋值默认值
var [a = 1] = [];
a === 1;
// 函数参数:解构赋值 + 默认值
function r({x, y, w = 10, h = 10}) {
return x + y + w + h;
}
r({x:1, y:2}) === 23;
Default + Rest + Spread
语法:
// 函数参数默认值
function f(x, y=12) {
// 如果不给y传值,或者传值为undefied,则y的值为12
return x + y;
}
f(3) == 15;
// rest
function f(x, ...y) {
// y是一个数组
return x * y.length;
}
f(3, "hello", true) == 6;
function f(x, y, z) {
return x + y + z;
}
f(...[1,2,3]) == 6; // array spread
const [a, ...b] = [1,2,3]; // array rest, b = [2, 3]
const {c, ...other} = {c: 1, d: 2, e: 3}; // object rest, other = {d: 2, e: 3}
const d = {...other}; // object spread