1.2.3.3.1 LiteJSE Javascript 编程指南

优质
小牛编辑
133浏览
2023-12-01

更新时间:2018-09-18 10:10:19

针对硬件资源不同的嵌入式设备,TinyEngine提供两种不同的JSE(LiteJSEDuktapeJSE),其中 LiteJSE是阿里巴巴自主开发JSE,目标是运行在资源非常有限的MCU或硬件,所耗资源 RAM<15KB,ROM<15KB,但支持的JS语法有限;另一种是DuktapeJSEDuktapeJSE 支持JavascriptES5.1DuktapeJSE采用开源项目 duktape
如需要支持Javascript 语法强的应用场景,或者RAM/ROM资源不是很敏感(RAM>256KB)的嵌入式设备,建议选用DuktapeJSE

LiteJSE Javascript 语法支持列表

 支持不支持备注
词法空白字符 行终结符 注释 Tokens 标识符名和标识符 保留字 字面量 自动分号插入Unicode 格式控制字符 正则表达式字面量声明变量/常量时,变量名/值表达式命名最长为63个字符 定义函数原型时,参数名称不要超过7个字符
类型undefined null true、false string Number 类型(整数、浮点数、指数) Object类型 列表规范类型 完结规范类型 属性描述符及属性标识符规范类型Infinity NaN Object 内部属性 引用规范类型 词法环境和环境记录项规范类型 对象内部方法的算法支持二进制/八进制/十六进制
类型转换SameValue 算法ToPrimitive ToBoolean ToNumber ToInteger ToInt32 ToUint32 ToUint16 ToString ToObject CheckObjectCoercible IsCallable可根据需要扩展支持
表达式主值表达式 左值表达式 后缀表达式(++,--) 一元运算符 (部份支持) 乘法运算符 加法运算符 位运算移位运算符 比较运算符 in 运算符 等值运算符 严格等于运算符 ( === ) 严格不等于运算符 ( !== ) 二元逻辑运算符 条件运算符 赋值运算符 逗号运算符delete 运算符 void 运算符 typeof 运算符 instanceof 运算符 二进制位运算符
语句块 变量语句 空语句 表达式语句 if 语句 迭代语句 for-in 语句 continue 语句 break 语句 with 语句 switch 语句 return 语句do-while 语句 标签语句 throw 语句 try 语句 debugger 语句default必须在最后一个case之后且default不能使用break结束字
全局对象undefined 全局对象的函数属性(部份支持) eval (x) 全局对象的构造器属性 (部份支持)NaN Infinity parseInt (string , radix) parseFloat (string) isNaN (number) isFinite (number) 处理 URI 的函数属性 
Object 对象作为函数调用 Object 构造器 Object 构造器Object 构造器的属性 Object 的 prototype 对象的属性 
Function 对象Function 对象 Function 构造器Function 构造器 Function 的 prototype 对象的属性 Function 的实例的属性 
Array 对象作为函数调用 Array 构造器 Array 构造器 数组原型对象的属性 (部份支持) Array.prototype.contains(element) Array.prototype.indexOf(searchElement) Array.prototype.push(element) Array.prototype.pop() Array.lengthArray 构造器的属性 [[GetOwnProperty]] ( P )可根据需求扩充
String 对象作为函数调用 String 构造器 String 构造器 字符串原型对象的属性(部份支持) String.prototype.charAt (pos) String.prototype.substring (start, end) String.prototype.substr(start[, length]) String.prototype.str.indexOf(searchValue) String.lengthString 构造器的属性可根据需求扩充
Math 对象random ( ) 可根据需求扩充
Date 对象 Date 对象 
RegExp 对象 RegExp ( 正则表达式 ) 对象 
Error 对象 Error Objects 不支持 
JSON 对象JSON 语法 parse (text) stringify(value)可根据需求扩充

LiteJSE Javascript 编写示例

基本语法示例

// 数值类型,变量,支持整数、浮点数、指数、八进制数、十六进制数、二进制数
var a = 345;
var b = 34.5;
var c = 3.45e2;
var d = 0377;
var e = 0xFF;
var f = 0b111;
var result = a==345 && b*10==345 && c==345 && d==255 && e==255 && f==7;

console.log('Number 测试 ' + ((result == 1 ) ? '成功' : '失败'));

// 值:undefined/null

var testUndefined;        // variable declared but not defined, set to value of undefined
var testObj = {};  

var a = 0;
if ((""+testUndefined) != "undefined") a = 1; // test variable exists but value not defined, displays undefined
if ((""+testObj.myProp) != "undefined") a = 2; // testObj exists, property does not, displays undefined
if (!(undefined == null)) a = 3;  // unenforced type during check, displays true
if (undefined === null) a = 4;// enforce type during check, displays false
if (null != undefined) a = 5;  // unenforced type during check, displays true
if (null === undefined) a = 6; // enforce type during check, displays false
if (undefined != undefined) a = 7;
if (!(undefined == undefined)) a = 8;
var b = undefined;
if (b !=undefined ) a = 9;    //  check for undefined
result = a==0;
console.log(testUndefined);
console.log('undefined/null 测试 ' + ((result == 1 ) ? '成功' : '失败'));

// Variable creation and scope from http://en.wikipedia.org/wiki/JavaScript_syntax
x = 0; // A global variable
var y = 'Hello!'; // Another global variable
z = 0; // yet another global variable

function f(){
  var z = 'foxes'; // A local variable
  twenty = 20; // Global because keyword var is not used
  return x; // We can use x here because it is global
}
// The value of z is no longer available

// testing
blah = f();
result = blah==0 && z!='foxes' && twenty==20 && (z==undefined);

console.log('变量及作用域 测试 ' + ((result == 1 ) ? '成功' : '失败'));


// if .. else
var a = 42;
if (a != 42)
  result = 0;
else
  result = 1;
console.log('if else 测试 ' + ((result == 1 ) ? '成功' : '失败'));


function Person(name) {
  this.name = name;
  this.kill = function() { this.name += " is dead"; };
}

var a = new Person("Kenny");
a.kill();
result = a.name == "Kenny is dead";

console.log('简单对象 测试 ' + ((result == 1 ) ? '成功' : '失败'));

obj1 = new Object();
obj1.food = "cake";
obj1.desert = "pie";

// 仅支持支持string 及 无传参的object对象的clone
obj2 = obj1.clone();
obj2.food = "kittens";

result = obj1.food=="cake" && obj2.desert=="pie";
console.log('简单对象 测试 ' + ((result == 1 ) ? '成功' : '失败'));


var Foo = {
 value : function() { return this.x + this.y; }
};

var a = { prototype: Foo, x: 1, y: 2 };
var b = new Foo(); 
b.x = 2;
b.y = 3;

var result1 = a.value();
var result2 = b.value();
result = result1==3 && result2==5;

console.log('嵌套对象 测试 ' + ((result == 1 ) ? '成功' : '失败'));

/*
r = Math.random();
console.log('Math.random 测试 ' + ((result = r != undefined ) ? '成功' : '失败'));


parsed = Integer.parseInt("42");
aChar = 'A';

result = parsed==42 && Integer.valueOf(aChar)==65 ;

console.log('Integer.parseInt/valueOf 测试 ' + ((result == 1 ) ? '成功' : '失败'));

*/

// test for shift
var a = (2<<2);
var b = (16>>3);

/*
// >>> (无符号右移) 暂不支持
var c = (-1 >>> 16);

*/

result = a==8 && b==2;
console.log('移位操作 测试 ' + ((result == 1 ) ? '成功' : '失败'));


var a=5.0/10.0*100.0;
var b=5.0*110.0;
var c=50.0/10.0;

result = a==50 && b==550 && c==5;
console.log('浮点数除法 测试 ' + ((result == 1 ) ? '成功' : '失败'));


var a =2;
var b=5;
var c=6;
result =  ((!a*b+a*10+a*b*c) == 80);

console.log('乘法/非操作 测试 ' + ((result == 1 ) ? '成功' : '失败'));

// 只支持后缀自增运算符
var a = 5;
var b = 5;
result = ((a++)==5) && (a==6) && ((b--) == 5) && (b==4);

console.log('后缀自增运算符 ++/-- 测试 ' + ((result == 1 ) ? '成功' : '失败'));


/*
当前语法不支持
var a = 5;
var b = 5;
result = ((++a)==6) && (a==6) && ((--b) == 4) && (b==4);

console.log('前置型 ++/-- 测试 ' + ((result == 1 ) ? '成功' : '失败'));

*/



/* Javascript eval */

// 对象转换需要加()
myfoo = eval("({ foo: 42 })");

result = eval("4*10+2")==42 && myfoo.foo==42;
console.log('eval 测试 ' + (result ? '成功' : '失败'));


/* Javascript eval */

mystructure = { a:39, b:3, addStuff : function(c,d) { return c+d; } };

mystring = JSON.stringify(mystructure); 

mynewstructure = eval("("+mystring+")");

result = mynewstructure.addStuff(mynewstructure.a, mynewstructure.b) == 42;

console.log('eval 测试 ' + (result ? '成功' : '失败'));


var array = JSON.parse('[1,2,3,true]');
console.log('JSON.parse 测试 ' + (array.length==4 ? '成功' : '失败'));
console.log(array);

var obj = JSON.parse('{"name":"alibaba","age":18}'); 
console.log('JSON.parse 测试 ' + (obj.age==18 ? '成功' : '失败'));
console.log(obj.name);

/*
  模块测试,  Modules.addCached 通过JS程序注册模块,代替从文件中读取

*/
var count=0;

Modules.addCached("a","module.exports.foo=1;");
var ta = require("a").foo;
count += ta;
console.log('ta=' + ta);

Modules.addCached("b","module.exports = {foo:1};");
var tb = require("b").foo;
count += tb;
console.log('tb=' + tb);

Modules.addCached("c","module.exports = 1;");
var tc = require("c");
count += tc;
console.log('tc=' + tc);

Modules.addCached("d","exports.foo = 1;");
var td = require("d").foo;
count += td;
console.log('td=' + td);

Modules.addCached("e","exports.foo = function(){ return 1;};");
var te = require("e").foo();
count += te;
console.log('te=' + td);


console.log(count);
console.log('Modules.addCache 测试'  +  ( (count == 5) ? '正确' : '失败'));

var myModule = "function myModule() {" +
"  this.hello = function() {" +
"    return 'hello!'; " +
"  }; " +
"  this.goodbye = function() {" +
"    return 'goodbye!';" +
"  }; " +
"}; " +
"module.exports = myModule; " ;

//console.log('myModule=' + myModule);

Modules.addCached("myModule", myModule);

myModule = require('myModule');
var myModuleInstance = new myModule();
console.log(myModuleInstance.hello());
console.log(myModuleInstance.goodbye());


var linkModule = " " +
"var mac = 'abc'; " +
"function Link() { " +
"    this.uuid = '1234';" +
"};" +
"var mLink = new Link();" +
"mLink.start = function(){" +
"    return this.uuid + ' start';" +
"};" +
"module.exports.Link = mLink;" +
"module.exports.mac = mac;";

Modules.addCached("linkModule", linkModule);
linkModule = undefined;

link = require('linkModule').Link;
console.log(link.start());
console.log(require('linkModule').mac);

// 验证module所分符号表使用无异常
/*
for(i=0; i<100; i++){
    console.log(link.start());
    console.log(require('linkModule').mac);
    console.log('te=' + require("e").foo());
    console.log('td=' + require("d").foo);
}

*/

字符串相关语法示例

foo = "foo bar stuff";
aStr = "ABCD";

aChar = aStr.charAt(0);
value = Integer.valueOf(aChar);

result = foo.length==13 && foo.indexOf("bar")==4 && 
         foo.substring(8,13)=="stuff"  && foo.substr(-3) == "uff" && aChar == 'A' &&
         Integer.valueOf(aChar)==65;

console.log('string 测试 ' + (result ? '成功' : '失败'));

function toMethod(event)
{
    var i;
    var j = event.length;
    var ch;
    var ret = '';

    for(i=0; i<j; i++){

        ch = event.charAt(i);

        if( ch == '/' )
            ret = ret + '.';
        else
            ret = ret + ch;
    }

    return ret;
}

var events = [
    "thing/event/property/post"
];

result = ( 'thing.event.property.post' == toMethod(events[0])  )

console.log('string 测试 ' + (result ? '成功' : '失败'));

console.log( toMethod(events[0]) );

数组相关语法示例

//变量有两种类型的值,即原始值和引用值。
// ECMAScript 有 5 种原始类型(primitive type),即 Undefined、Null、Boolean、Number 和 String
// array 是引用值变量

var a = [];
a[0] = 10;
a[1] = 22;

b = a;
b[0] = 5;

result = a[0]==5 && a[1]==22 && b[1]==22;

console.log('array引用传递 测试 ' + (result ? '成功' : '失败'));


// Array length test

myArray = [ 1, 2, 3, 4, 5 ];
myArray2 = [ 1, 2, 3, 4, 5 ];
myArray2[8] = 42;

result = myArray.length == 5 && myArray2.length == 9;

console.log('array length 测试 ' + (result ? '成功' : '失败'));

// test for array contains
var a = [1,2,4,5,7];
var b = ["bread","cheese","sandwich"];

result = a.contains(1) && !a.contains(42) && b.contains("cheese") && !b.contains("eggs");

console.log('array contains 测试 ' + (result ? '成功' : '失败'));

// Array.indexOf

var a = [8,9,10];
a["foo"]="lala";
a[3.333] = 3;

var r = [
  a.indexOf(8),
  a.indexOf(10),
  a.indexOf(42)
];

result = r[0]==0 && r[1]==2 && r[2]==undefined;

console.log('array indexOf 测试 ' + (result ? '成功' : '失败'));

var a = [1,2];

a.push(3);
a.push(4);
a.push('ok5');
a.push(6);

a.pop();

result = (a.length == 5) && (a.indexOf(2) == 1) && a.contains('ok5') && (!a.contains(6)) ;

console.log('array push/pop 测试 ' + (result ? '成功' : '失败'));

// 支持数组 in 操作
var x;
for (x in a)
{
    console.log('a[' + x + ']=' + a[x]);
}

if( 4 in a )
    console.log('4 in a , sucess');


/*
// test for array remove
var a = [1,2,4,5,7];

// 不支持object.remove
a.remove(2);
a.remove(5);

result = a.length==3 && a[0]==1 && a[1]==4 && a[2]==7;

// test for array join
var a = [1,2,4,5,7];

// join 不支持
result = a.join(",")=="1,2,4,5,7";

*/

循环及分支语法示例

// simple for loop
var a = 0;
var i;
for (i=1;i<10;i++) 
    a = a + i;
result = a==45;

console.log('for循环测试 ' + ((result == 1 ) ? '成功' : '失败'));

// simple for loop containing initialisation, using +=
var a = 0;
for (var i=1;i<10;i++) 
    a += i;
result = a==45;

console.log('for循环 += 测试 ' + ((result == 1 ) ? '成功' : '失败'));

// test break

var c1=0;
var c2=0;
var c3=0;

for (i=0;i<10;i++) {
  if (i>4) break;
  c1++;
}

for (i=0;i<10;i++) {
  c2++;
  if (i>4) break;
}

for (j=0;j<10;j++) { 
  for (i=0;i<10;i++) {
    if (i>4) break;
    c3++;
  }
  c3++;
}

result = (c1==5) && (c2==6) && (c3==10+5*10);

console.log('break测试 ' + ((result == 1 ) ? '成功' : '失败'));

// test continue

var c1=0;
var c3=0;

for (i=0;i<10;i++) {
  if (i>4 && i<8) continue;
  c1++;
}

for (j=0;j<10;j++) { 
  for (i=0;i<10;i++) {
    if (i>4 && i<8) continue;
    c3++;
  }
  c3++;
}

result = (c1==7) && (c3==10+7*10);

console.log('continue测试 ' + ((result == 1 ) ? '成功' : '失败'));

// switch-case-tests

////////////////////////////////////////////////////
// switch-test 1: case with break;
////////////////////////////////////////////////////
var a1=5;
var b1=6;
var r1=0;

switch(a1+5){
  case 6:
    r1 = 2;
    break;
  case b1+4:
    r1 = 42;
    break;
  case 7:
    r1 = 2;
    break;
}

console.log('switch case break测试 ' + ((result = r1 == 42 ) ? '成功' : '失败'));

////////////////////////////////////////////////////
// switch-test 2: case with out break;
////////////////////////////////////////////////////
var a2=5;
var b2=6;
var r2=0;

switch(a2+4){
  case 6:
    r2 = 2;
    break;
  case b2+3:
    r2 = 40;
    //break;
  case 7:
    r2 += 2;
    break;
}

console.log('switch 缺少break 测试 ' + ((result = r2 == 42 ) ? '成功' : '失败'));

////////////////////////////////////////////////////
// switch-test 3: case with default;
////////////////////////////////////////////////////
var a3=5;
var b3=6;
var r3=0;

switch(a3+44){
  case 6:
    r3 = 2;
    break;
  case b3+3:
    r3 = 1;
    break;
  default:
    r3 = 42;
}

console.log('switch default 测试 ' + ((result = r3 == 42 ) ? '成功' : '失败'));


/*
// switch-test 4: case default before case;  语法分析出错
default必须在最后一个case之后且default不能使用break结束字
var a4=5;
var b4=46;
var r4=40;

switch(a4+44){
  default:
    r4 = 42;
  case 6:
    r4 = 2;
    break;
  case b4+3:
    r4 = 1;
    break;
}
console.log('switch default before case 测试 ' + ((result = r4 == 42 ) ? '成功' : '失败'));

*/

函数相关语法示例

// simple function
var b = function(x)
{
    return x;
};

var a = b(10)+b(20);

function add(x,y)
{
    return x+y;
}
var result;
result = (a == 30) && (add(3,6)==9);
console.log('简单函数测试 ' + ((result == 1 ) ? '成功' : '失败'));

// simple function scoping test
var a = 7;
function add(x,y) { var a=x+y; return a; }
result = add(3,6)==9 && a==7;
console.log('简单函数+作用域 测试 ' + ((result == 1 ) ? '成功' : '失败'));

// functions in variables
var bob = {};
bob.add = function(x,y) { return x+y; };

result = bob.add(3,6)==9;

console.log('对象函数 测试 ' + ((result == 1 ) ? '成功' : '失败'));

// functions in variables using JSON-style initialisation
var bob = { add : function(x,y) { return x+y; } };

result = bob.add(3,6)==9;

console.log('JSON描述对象函数 测试 ' + ((result == 1 ) ? '成功' : '失败'));

// double function calls
function a(x) { return x+2; }
function b(x) { return a(x)+1; }
result = a(3)==5 && b(3)==6;

console.log('嵌套调用函数 测试 ' + ((result == 1 ) ? '成功' : '失败'));

// recursion
function a(x) {
  if (x>1)
    return x*a(x-1);
  return 1;
}
result = a(5)==1*2*3*4*5;
console.log('嵌套调用函数 测试 ' + ((result == 1 ) ? '成功' : '失败'));

// references with functions
// 函数参数变量可以存在两种类型的值,即原始值和引用值。
// ECMAScript 有 5 种原始类型(primitive type),即 Undefined、Null、Boolean、Number 和 String

var a = 42;
var b = [];
b[0] = 43;

function foo(myarray) {
  myarray[0]++;
}

function bar(myvalue) {
  myvalue++;
}

foo(b);
bar(a);

result = a==42 && b[0]==44;
console.log('函数参数 原始值和引用值 测试 ' + ((result == 1 ) ? '成功' : '失败'));

// 全局变量及作用域

z = 0;
function addstuff() {
 var count=0;
 z = function() {
  count++;
  return count;
 };
}

addstuff();

result = z();

//console.log(count);  // BoneEngine > undefined

console.log(result);

console.log('全局变量及作用域 测试 ' + ((result == 1 ) ? '成功' : '失败'));


var func = addstuff;

console.log(func);   // BoneEngine > function

if( func )
  console.log('if判断函数 sucess');
else
  console.log('if判断函数 fail');