JavaScriptCore

  JavaScript这门所谓的脚本的语言,在两年前我从事Web开发的时候,还只是把它当做HTML中操作DOM元素来改变一些常见属性的工具。那时我对JavaScript的认识还很局限,如今随着HTML5的火爆,JavaScript被我重新认知,它作为动态语言的强大,V8引擎的优化以及配合CSS3构建移动端网站的优势让我欣喜。今天介绍下苹果的JavaScriptCore,以后有时间会专门写一个JavaScript的专题,包括JavaScript基础、动画等内容……

 

  没认识JavaScriptCore之前,如果想在Object-c中使用JavaScript代码,一般都是在webview这个uikit中(webview内置webkit引擎,解析JavaScript代码),如下这段代码主要调用webview的stringByEvaluatingJavaScriptFromString:方法,将HTML中所有li标签里的href属性进行修改。

NSMutableString *mutableStr=[NSMutableString string];
    [mutableStr appendString:@"var lis=document.getElementsByTagName('li');"];
    [mutableStr appendString:@"for(var i=0;i<lis.length;i++){"];
    [mutableStr appendString:@"var aHref=lis[i].children[0].href;"];
    [mutableStr appendString:@"var startIndex=aHref.indexOf('(');"];
    [mutableStr appendString:@"var endIndex=aHref.indexOf(')');"];
    [mutableStr appendString:@"var newStr=aHref.substr(startIndex+2,endIndex-startIndex-3);"];
    [mutableStr appendString:@"lis[i].children[0].href='objc-'+newStr;"];
    [mutableStr appendString:@"}"];
    [webView stringByEvaluatingJavaScriptFromString:mutableStr];
View Code

 

  JavaScriptCore是什么呢?它其实是苹果封装的一个JavaScrip代码的运行环境(可见苹果对JavaScript也从小三扶上位了),可以很容易的创建代码来创建JavaScript的变量、进行各种计算甚至是定义function

  使用前需导入#import <JavaScriptCore/JavaScriptCore.h>

使用方法:

1、创建环境 

JSContext *context=[[JSContext alloc] init];

2、调用evaluateScript创建JavaScript代码

  [context evaluateScript:@"var num=5+5"];
    [context evaluateScript:@"var names=['Lusieke','Lemon','Honey']"];
    [context evaluateScript:@"var triple=function(value){return value * 3}"];
    [context evaluateScript:@"var sum=function(num1,num2){return num1+num2}"];
View Code

3、任何出自JSContext的值都被包裹在一个JSValue对象中。像JavaScript这样的动态语言需要一个动态类型(var),所以JSValue包装了每一个可能的JavaScript值:字符、数字、数组、对象和方法。JSValue包括一系列方法用于访问其可能的值以保证有正确的Foundation类型

    JSValue *tripNum=[context evaluateScript:@"num"];
//输出10,即定义的JavaScript脚本中var num=5+5的值    
NSLog(@"triple :%d",[tripNum toInt32]);
    
    JSValue *names=[context evaluateScript:@"names"];
    //输出names数组的值
    NSLog(@"names :%@",[names toArray]);
View Code

4、JSContext和JSValue实例使用下标的方法,我们可以很容易的访问到我们之前创建的context的任何值。JSContext需要一个字符串下标,而JSValue允许字符串或整数下标来得到里面的对象和数组

 JSValue *names=context[@"names"];
    JSValue *initialName=names[0];
    NSLog(@"The first name :%@",[initialName toString]);
View Code

5、如何调用定义的JavaScript函数?JSValue包装了一个JavaScript函数,我们可以在Object-c代码中使用Foundation类型作为参数来直接调用该函数

    JSContext *context=[[JSContext alloc] init];
    [context evaluateScript:@"var sum = function sum(num1,num2){return num1+num2;}"];
    JSValue *sumFunc=[context[@"sum"] callWithArguments:@[@2,@3]];
    NSLog(@"2+3的和=%d",[sumFunc toInt32]);
View Code

输出内容:

2015-03-12 11:23:32.787 javaScriptCore[742:140647] 2+3的和=5

程序中JSValue类型的变量context[@"sum"]通过callWithArguments:传递Foundation类型的变量@2,@3来调用JavaScript函数sum,并输出计算后的值

6、对照第5点,JavaScript如何调用定义在Object-c中的方法呢?比较常用的方法是使用Block(大块头有大能力)

context[@"simplifyString"]=^(NSString *input){
        NSMutableString *mutableString=[input mutableCopy];
        CFStringTransform((__bridge CFMutableStringRef)mutableString, NULL, kCFStringTransformToLatin, NO);
        CFStringTransform((__bridge CFMutableStringRef)mutableString, NULL, kCFStringTransformStripCombiningMarks, NO);
        return mutableString;
    };
    NSLog(@"%@",[context evaluateScript:@"simplifyString('안녕하새요!')"]);
View Code

OC定义的方法保存在Block类型的变量并直接塞到context环境中(这样才会被JavaScript调用)成为JavaScript的方法,之后用同样的evaluateScript:传参调用,这就又回到第5点的内容了,应该很好理解了吧……

7、JavaScript的调试一直是很多新手头疼的问题,JavaScriptCore既然风转了JavaScript的运行环境,自然有自己调试JS的招数

context.exceptionHandler=^(JSContext *context, JSValue *exception){
        NSLog(@"JS Error :%@",exception);
    };

JSContext通过设置上下文的exceptionHandler属性,可以捕获JS的运行时错误,

exceptionHandler是一个接收一个JSContext引用和异常本身的回调处理

    JSContext *context=[[JSContext alloc] init];
    [context evaluateScript:@"var summ = function sum(num1,num2){return num1+num2;}"];
    context.exceptionHandler=^(JSContext *context, JSValue *exception){
        NSLog(@"JS Error :%@",exception);
    };
    JSValue *sumFunc=[context[@"sum"] callWithArguments:@[@2,@3]];
    NSLog(@"2+3的和=%d",[sumFunc toInt32]);
View Code

这段跟第5点相同的代码中,故意将方法名sum写成summ,有了exceptionHandler后的生活编译器会妥妥的给你报个error

2015-03-12 11:39:51.060 javaScriptCore[1088:180110] JS Error :TypeError: undefined is not an object

一个经典的JS错误undefined

大致就介绍这么多,希望对看到的朋友有点用……

 

posted @ 2015-03-12 11:42  luseike  阅读(2047)  评论(0编辑  收藏  举报