`
jsntghf
  • 浏览: 2532530 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

JavaScriptCore入门

    博客分类:
  • iOS
阅读更多

一、Objective-C中执行JavaScript代码

#import <JavaScriptCore/JavaScriptCore.h>

int main(int argc, char *argv[]) {
    JSContext *context = [[JSContext alloc] init];
    JSValue *result = [context evaluateScript:@"1 + 2"];
    NSLog(@"1 + 2 = %d", [result toInt32]);     // 1 + 2 = 3
    
    return 0;
}

 

二、Objective-C中调用JavaScript函数

#import <JavaScriptCore/JavaScriptCore.h>

int main(int argc, char *argv[]) {
    JSContext *context = [[JSContext alloc] init];
    [context evaluateScript:@"function sum(a, b){ return a + b; }"];
    JSValue *sum = context[@"sum"];
    JSValue *result = [sum callWithArguments:@[@1, @2]];
    NSLog(@"sum(1, 2) = %d", [result toInt32]);     // sum(1, 2) = 3
    
    return 0;
}

 

三、创建JavaScript变量

#import <JavaScriptCore/JavaScriptCore.h>

int main(int argc, char *argv[]) {
    JSContext *context = [[JSContext alloc] init];
    JSValue *intVar = [JSValue valueWithInt32:123 inContext:context];
    context[@"bar"] = intVar;
    JSValue *result = [context evaluateScript:@"bar++"];
    NSLog(@"bar = %d", [result toInt32]);     // bar = 123
    
    return 0;
}

更简单的方式:

#import <JavaScriptCore/JavaScriptCore.h>

int main(int argc, char *argv[]) {
    JSContext *context = [[JSContext alloc] init];
    [context evaluateScript:@"var bar = 123;"];
    NSLog(@"bar = %@", context[@"bar"]);     // bar = 123
    
    return 0;
}

 

四、监控JavaScript的异常

#import <JavaScriptCore/JavaScriptCore.h>

int main(int argc, char *argv[]) {
    JSContext *context = [[JSContext alloc] init];
    
    context.exceptionHandler = ^(JSContext *ctx, JSValue *exception) {
        NSLog(@"%@", exception);        // ReferenceError: Can't find variable: name
    };
    
    [context evaluateScript:@"name.firstName = Eric"];
    
    return 0;
}

 

五、JavaScript中调用Objective-C函数

#import <JavaScriptCore/JavaScriptCore.h>

int main(int argc, char *argv[]) {
    JSContext *context = [[JSContext alloc] init];
    
    context[@"sum"] = ^(int a, int b) {
        return a + b;
    };
    
    JSValue *result = [context evaluateScript:@"sum(1, 2)"];
    
    NSLog(@"sum(1, 2) = %d", [result toInt32]);     // sum(1, 2) = 3
    
    return 0;
}

 

六、函数内部为JSContext定义新的变量

#import <JavaScriptCore/JavaScriptCore.h>

int main(int argc, char *argv[]) {
    JSContext *context = [[JSContext alloc] init];
    
    context[@"sum"] = ^(int a, int b) {
        JSContext *ctx = [JSContext currentContext];
        ctx[@"foo"] = @123;
        return a + b;
    };

    JSValue *result = [context evaluateScript:@"sum(1, 2)"];
    NSLog(@"sum(1, 2) = %d", [result toInt32]);   // sum(1, 2) = 3
    NSLog(@"foo = %@", context[@"foo"]);     // foo = 123
    
    return 0;
}

不能使用context[@"foo"] = @123,必须使用[JSContext currentContext]来获取当前的context,此时获取到的context和context[@"sum"]中的context相同。

 

七、JavaScript中调用Objective-C函数时动态传参

#import <JavaScriptCore/JavaScriptCore.h>

int main(int argc, char *argv[]) {
    JSContext *context = [[JSContext alloc] init];
    
    context[@"count"] = ^() {
        NSArray *array = [JSContext currentArguments];
        return array.count;
    };

    JSValue *result = [context evaluateScript:@"count(1, 2)"];
    NSLog(@"count(1, 2) = %d", [result toInt32]);   // count(1, 2) = 2
    
    JSValue *result2 = [context evaluateScript:@"count(1, 2, 3, 4, 5, 6)"];
    NSLog(@"count(1, 2, 3, 4, 5, 6) = %d", [result2 toInt32]);   // count(1, 2, 3, 4, 5, 6) = 6
    
    return 0;
}

 

八、JavaScript中操作Objective-C的类

(1)Point3D.h

#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h>

@protocol Point3DExport <JSExport>

@property double x;
@property double y;
@property double z;

- (double)length;

@end

@interface Point3D : NSObject <Point3DExport> {
    JSContext *context;
}

- (id)initWithContext:(JSContext *)ctx;

@end

 

(2)Point3D.m

#import "Point3D.h"

@implementation Point3D

@synthesize x;
@synthesize y;
@synthesize z;

- (id)initWithContext:(JSContext *)ctx {
    if (self == [super init]) {
        context = ctx;
        context[@"Point3D"] = [Point3D class];
    }
    
    return self;
}

- (double)length {
    return sqrt(self.x * self.x + self.y * self.y + self.z * self.z);
}

@end

 

(3)调用示例

#import <JavaScriptCore/JavaScriptCore.h>
#import "Point3D.h"

int main(int argc, char *argv[]) {
    JSContext *context = [[JSContext alloc] init];
    Point3D *point3D = [[Point3D alloc] initWithContext:context];
    point3D.x = 1;
    point3D.y = 2;
    point3D.z = 3;
    context[@"point3D"] = point3D;
    JSValue *result = [context evaluateScript:@"point3D.x = 4;point3D.y = 5;point3D.z = 6;point3D.length()"];
    NSLog(@"point3D.length() = %f", [result toDouble]);    // point3D.length() = 8.774964
    
    return 0;
}

 

这里Point3D的定义中遵循了JSExport协议,协议中定义了属性(x、y、z)和方法(length)用来暴露给JavaScript,从而使JavaScript可以使用这些属性(x、y、z)和方法(length)。

 

九、将JavaScript提取到单独的JS文件中

(1)test.js

var foo = function(a) {
    return "I'm foo in JS. Value is " + a;
};

function bar(a) {
    return "I'm bar in JS. Value is " + a;
};

foo(123);
bar(456);

 

(2)调用示例

#import <JavaScriptCore/JavaScriptCore.h>

void loadScript(JSContext *context, NSString *fileName) {
    NSString *filePath = [NSString stringWithFormat:@"%@/JS/%@", [[NSBundle mainBundle] resourcePath], fileName];
    NSString *script = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    
    [context evaluateScript:script];
}

int main(int argc, char *argv[]) {
    JSContext *context = [[JSContext alloc] init];
    loadScript(context, @"test.js");
    
    return 0;
}

 

十、给JavaScript添加console.log功能

(1)Console.h

#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h>

@protocol ConsoleExport <JSExport>

- (void)log;

@end

@interface Console : NSObject <ConsoleExport> {
    JSContext *context;
}

- (id)initWithContext:(JSContext *)ctx;

@end

 

(2)Console.m

#import "Console.h"

@implementation Console

- (id)initWithContext:(JSContext *)ctx {
    if (self == [super init]) {
        context = ctx;
        context[@"Console"] = [Console class];
    }
    
    return self;
}

- (void)log {
    NSArray *args = [JSContext currentArguments];
    NSLog(@"%@", [args componentsJoinedByString:@","]);
}

@end

 

(3)test.js

var foo = function(a) {
    return "I'm foo in JS. Value is " + a;
};

function bar(a) {
    return "I'm bar in JS. Value is " + a;
};

console.log(foo(123));     // I'm foo in JS. Value is 123
console.log(bar(456));     // I'm bar in JS. Value is 456

 

(4)调用示例

#import <JavaScriptCore/JavaScriptCore.h>
#import "Console.h"

void loadScript(JSContext *context, NSString *fileName) {
    NSString *filePath = [NSString stringWithFormat:@"%@/JS/%@", [[NSBundle mainBundle] resourcePath], fileName];
    NSString *script = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    
    [context evaluateScript:script];
}

int main(int argc, char *argv[]) {
    JSContext *context = [[JSContext alloc] init];
    context[@"console"] = [[Console alloc] initWithContext:context];
    loadScript(context, @"test.js");
    
    return 0;
}

 

十一、完善JavaScript的console功能

(1)mock-console.js

(function(){
    console.debug = console.info = console.warn = console.error = console.log;
  
    var timer = {};
  
    console.time = function(name) {
        timer[name] = Date.now();
    };
  
    console.timeEnd = function(name) {
        var timeStart = timer[name];
 
        if (!timeStart)
            return;
  
        var timeElapsed = Date.now() - timeStart;
        console.log(name + ":" + timeElapsed + "ms");
        delete timer[name];
    };
  
    console.log("=== mock console ok ===");
})();

 

(2)test.js

console.log(Date.now());  // 1433760502752
console.time("sum");	  
var sum = 0;

for (var i = 0; i < 1E5; i++) {
    sum += i;
}

console.info(sum);       // 4999950000
console.timeEnd("sum");  // sum:32ms

 

(3)调用示例

int main(int argc, char *argv[]) {
    JSContext *context = [[JSContext alloc] init];
    context[@"console"] = [[Console alloc] initWithContext:context];
    loadScript(context, @"mock-console.js");
    loadScript(context, @"test.js");
    
    return 0;
}

 

十二、JavaScript获取硬件信息

(1)test.js

console.log(language());      // en
console.log(deviceInfo());    // iPhone Simulator,iPhone OS

 

(2)调用示例

#import <JavaScriptCore/JavaScriptCore.h>
#import <UIKit/UIKit.h>
#import "Console.h"

void loadScript(JSContext *context, NSString *fileName) {
    NSString *filePath = [NSString stringWithFormat:@"%@/JS/%@", [[NSBundle mainBundle] resourcePath], fileName];
    NSString *script = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    
    [context evaluateScript:script];
}

void prepareLanguage(JSContext *context) {
    context[@"language"] = ^() {
        NSString *language = [NSLocale preferredLanguages][0];
        
        return language;
    };
}

void prepareDeviceInfo(JSContext *context) {
    context[@"deviceInfo"] = ^() {
        NSString *deviceName = [[UIDevice currentDevice] name];
        NSString *systemName = [[UIDevice currentDevice] systemName];
        
        return @[deviceName, systemName];
    };
}

int main(int argc, char *argv[]) {
    JSContext *context = [[JSContext alloc] init];
    context[@"console"] = [[Console alloc] initWithContext:context];
    prepareLanguage(context);
    prepareDeviceInfo(context);
    loadScript(context, @"test.js");
    
    return 0;
}

 

更深入的学习,可以参考官方的源码,注释写的很详细。

分享到:
评论

相关推荐

    移动端:手把手带你入门跨平台UI开发框架Flutter,看完这篇-flutter框架

    ### 跨平台UI开发框架Flutter入门详解 #### 一、Flutter框架概览 **Flutter** 是一款由Google推出的跨平台移动应用开发框架,旨在通过一套代码库就能开发出高质量的iOS和Android应用。该框架的核心优势在于其高效...

    Swift使用Echarts的Demo

    webView.evaluateJavaScript("myChart.setOption({\n title : {\n text: 'ECharts入门示例'\n },\n tooltip : {\n trigger: 'axis'\n },\n legend: {\n data:['销量']\n },\n xAxis : {\n data : [\"衬衫\",\"羊毛...

    iOS 7 by Tutorials 瘦身版 pdf

    第三部分讨论了iOS 7的一些重大新特性,包括但不限于使用NSURLSession进行网络编程、多任务处理的入门和进阶主题、JavaScriptCore框架、AirDrop功能以及对等网络连接。 现在,让我们细致地讨论一些重要知识点: 1....

    廖祜秋-React Native for Android

    演讲可能详细讨论了React Native应用的性能问题及其优化方案,并介绍了React Native在不同设备上的JavaScript引擎,如iOS上的JavaScriptCore和Android上的V8引擎,以及它们的调试方式。 知识点七:ES6和JSX语法 ES6...

    iOS 7 by Tutorial (pdf)

    JavaScriptCore框架的引入使得JavaScript代码能够在iOS应用中运行,本书介绍如何在Swift或Objective-C中使用JavaScriptCore,包括如何执行JavaScript代码和从JavaScript调用Objective-C或Swift代码。 AirDrop是iOS ...

    iOS_7_by_Tutorials_1_0.pdf

    - JavaScriptCore是一个支持JavaScript脚本的框架。 - 介绍了如何在iOS应用中嵌入JavaScript代码,实现脚本化编程。 5. **第20章:AirDrop**: - AirDrop是一种允许iOS设备之间无线传输文件的技术。 - 本章讲解...

    Webkit学习资

    - **Webkit结构简介.doc**:该文档可能详细介绍了Webkit的整体架构和各个组件的功能,是初学者入门的好资料。 - **webkit中的Chrome和ChromeClient.pdf**:Chrome和ChromeClient是Webkit中两个重要的概念,分别代表...

    hekla:Hekla for Hacker News(开源React Native应用)

    Hekla for Hacker News 适用于Hacker News的iOS和Android客户端。...native-navigation v2 react-native-config Android上JavaScriptCore 钥匙串来存储敏感数据带触控笔CSS模块用于自定义本机代码的补丁程序包入门您

    JavaScript.pdf

    基本语法入门包括变量声明、数据类型、条件控制、循环、函数等。变量声明可以使用 var、let、const 三种方式,let 和 const 是 ES6 新增的声明方式。数据类型包括 number、string、Boolean、object 等,object 可以...

    babel-preset-react-native-web3:用于响应本机,web3和babel 6的babel预设

    这使得使用crypto-browserify和纯JavaScript的randombytes小实现在JavascriptCore上进行crypto工作。 可以认为是解决方法,缓冲区和进程全局变量。 总览 babel的预设,可以直接使用进行。 入门 # Install ...

    JavaScript - JavaScript from Beginner to Professional

    - **JavaScriptCore (JSC)**:Apple Safari浏览器的JavaScript引擎。 #### 五、利用浏览器控制台调试JavaScript 浏览器的开发者工具通常包含一个控制台(Console),可以用来输出日志、执行JavaScript命令以及调试...

    Beginning iPhone and iPad Web Apps - Scripting with HTML5, CSS3 and JavaScript

    在iOS设备上,JavaScript还可以通过WebKit框架,特别是其JavaScriptCore,与Objective-C或Swift进行交互,实现原生功能的封装。 本书《初识iPhone与iPad Web应用》将深入讲解如何结合这三大技术,利用Web App开发...

    郝振明-React Native 移动技术在企业架构的应用

    React Native的最大优势在于其利用原生渲染,从而提供了更佳的用户体验,并且采用Web语言(JavaScript)作为基础开发语言,这大大降低了开发者的入门门槛。其支持在不发布新版本的情况下,通过网络直接更新应用内容...

Global site tag (gtag.js) - Google Analytics