Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
introduce to Mayjs
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
zhongxingdou
September 25, 2014
Programming
71
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
introduce to Mayjs
May JavaScript better
zhongxingdou
September 25, 2014
Other Decks in Programming
See All in Programming
現場と育てるRailsモデリング 〜Spreadsheetから始めたモデル設計〜
siroemk
2
590
UnityでSystem.Net.WebSocketsなWebSocketサーバが動かないのでUnity Monoのコードを覗いてみた / about implementing websocket server with unity mono
drumath2237
1
610
ハーネス設計入門 〜 基礎知識の整理から実務へのステップアップ 〜
kinopeee
28
32k
なぜCTOを降りてFDEを選んだのか?〜なぜプロダクト企業がFDEで顧客の現場に踏み込むのか〜
gonta
1
210
[Rails World 2026] Durable orchestration on Rails: from continuation to workflow
palkan
1
750
Railsバージョンを4倍にした話
optim
0
360
AWSに止められる覚悟してますか?
morizo_1984
2
540
パスワード再設定メールのURLについて知っておこう
uyuki234
0
160
contenteditable と日本語入力に向き合う
colorful12
0
200
IBM Bob Dojo #1 仕様駆動開発入門
oniak3ibm
PRO
0
390
動作中のプログラムの中身をリアルタイムに覗く / Realtime Debugger for CSharp with Roslyn
prota
1
1.9k
AI時代のコードレビューは人に向けるな、仕組みに向けろ
texmeijin
5
3.7k
Featured
See All Featured
Google's AI Overviews - The New Search
badams
0
1.6k
Become a Pro
speakerdeck
PRO
31
6.3k
Statistics for Hackers
jakevdp
799
230k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
20k
[RailsConf 2023] Rails as a piece of cake
palkan
59
7.1k
How to build a perfect <img>
jonoalderson
1
6.1k
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
640
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.7k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.3k
Bash Introduction
62gerente
615
220k
AI: The stuff that nobody shows you
jnunemaker
PRO
10
1.2k
Transcript
May 为JavaScript更出彩 js .
原则 • 专注于⽤用JavaScript让JavaScript更好 • 保持简单,明晰,轻量 • 保持JavaScript还是JavaScript
About me • ZhongXingdou! • BFE Guangzhou •
[email protected]
•
http://bellstar.iteye.com/
May.js简介 • 对JavaScript语⾔言进⾏行增强,让它更锋利更简洁 • 功能由⼀一系列$开头的类关键字函数来完成 • 提供Class Module Interface等OO要素 •
提供⼀一些便利⽅方法让代码更易读和精简
内容 • 可重⽤用的module • 聪明的wrap • 让interface出⼭山 • class和⼩小sugar们
可重⽤用的module • Ruby的module • 声明May.js的module • include module
Ruby的module class User < ActiveRecord::Base acts_as_votable end
! HaiMeimei = User.new LiLei = User.new HaiMeimei.vote_by :voter => Lilei, :vote => 'like'
声明May.js的module var Voteable = $module({ onIncluded: function(person){
person.votes = []; }, voteBy: function(person, voter, vote){ person.votes.push({voter: voter, vote: vote}); } });
class include module var User = $class({}); User.include(Voteable, {methodize:
true}); ! HaiMeimei = new User(); LiLei = new User(); HaiMeimei.voteBy(LiLei, "like"); !
object include module ZhangJun = {} $include(ZhangJun, Voteable, {methodize:
true}); ! ZhangJun.voteBy(LiLei, "hate"); !
IModuleOption IModuleOption = { context: Object, //回调onIncluded和wrap⽅方法时⽤用
methodize: Boolean, //是否wrap⽅方法 methodizeTo: Function, //wrap⽅方法时指定参数 supports: Array, //可以⽀支持到的class和prototype stopCallback: Boolean //停⽌止回调onIncluded() } !
IModule IModule = { __option__: IModuleOption,
onIncluded: Function } !
可重⽤用的module • onIncluded()回调 • include到class或者object • module的method如⽤用第⼀一参数代表include它的对象, include时设置option.methodize为true • 可通过参数控制如何include
• module可以包含元信息,作为include时的默认参数 • module不⼀一定是从$module()出来的
聪明的wrap • wrap对象初体验 • 全局和局部Wrapper Map • 为对象查找Wrapper
wrap对象初体验
$
$( "button.continue" ).html( "Next Step..." ) ! $(
"#button-‐container button" ).on( "click", function( event ) { hiddenBox.show(); });
_
_.extend({name: 'moe'}, {age: 50}); ! _({name: 'moe'}).extend({age: 50});
8.next() 'abc'.reverse()
$(8).next() $('abc').reverse() ! _(8).next() _('abc').reverse()
M
None
None
var stringEx = { reverse: function(s){
return s.split("").reverse().join(""); } } ! M.$.reg(stringEx, String, {methodize: true}); ! M.$("abcd").reverse();
! var s = new String('abcd'); M.$(s).reverse(); s.reverse;
//undefined ⾮非侵⼊入式的扩展对象$!
M.$$(s); s.reverse(); //dcba 侵⼊入式的扩展对象$$!
“侵⼊入对象并不可怕,只要不搞坏别⼈人也要⽤用的”
M(function($, $$){ "use strict"; !
var stringEx = { reverse: function(s){ return s.split("").reverse().join(""); }, __option__: {methodize: true} } $.reg(stringEx, String); ! var s = $$("abcd"); s.reverse(); //dcba }); M式写法—strict版!
M(function(){ eval(M()); !
var stringEx = { reverse: function(s){ return s.split("").reverse().join(""); }, __option__: {methodize: true} } $.reg(stringEx, String); ! var s = $$("abcd"); s.reverse(); //dcba }); M式写法!
M() '…… var $=_temp14111185263705411698832176626.value[\’$\’], $$=_temp14111185263705411698832176626.value[\’$$\'], $reg=_temp14111185263705411698832176626.value[\’$reg\']; delete
_temp14111185263705411698832176626;'
"use strict" No!
• eval(M()) • $, $$ • methodize
methodize function methodize(fn, firstParam, getFirstParam) {
return function() { //获取第⼀一个参数 var p1 = firstParam || this; if(getFirstParam) p1 = getFirstParam(p1); ! //把第⼀一个参数和其他参数放在⼀一起 var slice = Array.prototype.slice; var args = [p1].concat(slice.call(arguments)); ! return fn.apply(this, args); } }
methodize var panel = {}; var ContainerEx = {
collapse: function(ui){ //ui.body.display = "none"; } } ! panel.collapse = methodize(ContainerEx.collapse, panel); ! panel.collapse();
注册Wrapper和wrap对象基本⽤用法 • M.$.reg() 注册Wrapper • M.$()使⽤用proxy⽆无侵⼊入的wrap对象(像jQuery) • M.$$()直接扩展对象本⾝身 • 使⽤用M(function($,$$){…})在局部使⽤用$(),$$()
全局和局部Wrapper Map
M.$() M.$$() M.$.reg() ! ! $()
$$() $.reg() 局部 全局 M.Wrapper $() $$() $.reg() @__map__ findWrappersByType() M.Wrapper $() $$() $.reg() @__map__ findWrappersByType()
//BaseExtend.js var StringEx = {
truncate: function(s, count){ return s.length <= count ? s : s.substr(0, count) + "…"; }, __option__: {methodize: true} } M.$.reg(StringEx, String); ! M.$("abcdefghijklmn").truncate(6); //abcdef… ! !
//BaseExtend.js var StringEx = {
truncate: function(s, count){}, __option__: {methodize: true} } M.$.reg(StringEx, String); ! ! ! ! //page.js M(function($, $$){ var nickNameEx = { atName: function(s){ return "@" + s } } $.reg(nickNameEx, String, {methodize: true}); ! $("abcdefghijklmn").truncate(6); //abcdef… $("Jim").atName(); //@Jim }); ! M.$("Jim").atName; //undefined
! ! //page.js M(function($, $$){ var nickNameEx =
{ atName: function(s){ return "@" + s } } $.reg(nickNameEx, String, {methodize: true}); ! ! M(function($2, $$2){ $2.reg({twice: function(){}}, String, {methodize: true}); $2("abcd").twice(); //abcdabcd ! $("Jim").atName(); //@Jim $2("Jim").atName; //undefined }); ! });
为对象查找Wrapper
Wrapper可以注册到 • valueType M.$.reg(StringEx, String); • prototype M.$.reg(Observer, UI.prototype);
• interface M.$.reg(List, IIterator);
Wrapper查找 Obj __proto__ Object.prototype __proto__ Wrappers Wrappers Wrappers __interfaces__ __interfaces__
__interfaces__ __interfaces__ Wrappers
如何wrap实现了相同interface的对象
让对象⾃自⼰己表明已实现interface
让interface出⼭山 • 动态语⾔言是否需要显式interface? • 声明May.js的interface并使⽤用 • 利⽤用类型判断实现overload重载
动态语⾔言是否需要interface?
DuckType ! 不检查,给我啥我都直接⽤用,报错了正好修bug
Java C# ! 检查有没有实现指定接⼝口对象,不能⽤用,编译都过不了
接⼝口对象 interface IA{ int x; int y; } interface IB{
int x; int y; } != namespace Ali.biz namespace Jd.biz ⽤用你的代码可以,还要我的代码⾥里打上你公司的标记
http://www.cnblogs.com/yjf512/archive/2012/06/09/2543628.html
接⼝口检查 ! 不是核对接⼝口对象 ! ⽽而是核对接⼝口成员
动态语⾔言是否有interface?
动态语⾔言的interface是隐⼠士
动态语⾔言 ! 既会检查参数 ! 也会检查成员 还可以通过这两种代码发现隐⼠士interface
动态语⾔言,interface?可以有 ! 检查对象成员,让隐⼠士interface出⼭山
声明May.js的interface并使⽤用
声明May.js的interface var IPerson = $interface({ name: String,
age: Number, sayHi: [IPerson, String], interest: Array });
实现May.js的interface var Person = $class({ initialize: function(name, age,
interest){ $check($is(IPerson.name, name)); $check($is(IPerson.age, age)); $check($is(IPerson.interest, interest)); … } sayHi: function(person, saySomething){ $checkArgu(); //$checkArgu(IPerson, String); … } }); ! $implement(IPerson, Person);
终于在⼀一个地找到需要怎样的对象 ! 集中管理更⽅方便
隐式接⼝口会过时,显式的才可靠
$support() — 检查interface var IPatient = $interface({ name:
String, age: Number }); ! var XiaoMing = new Person("xiaoming", 13, ["swimming","singing"]); ! var Hospital = { records: {}, registration: function(patient, department){ $support(IPatient, patient); this.records.add(patient, department); } } !
Person不⽤用实现IPatient, IPassenger,IVisitor...
如何wrap实现了相同interface的对象
利⽤用对象的已实现interface元信息 obj.__interfaces__
这样不就回到检查接⼝口对象了吗?
是的,为了性能考虑,根据已注册的 所有interface⼀一个⼀一个验证成员, 太。。。,考虑局部$() $()⽀支持。
让interface出⼭山 • 动态语⾔言也可以有interface,要正确使⽤用 • interface有利对象验证,⽅方便统⼀一集中管理 • $interface() • $implement() •
$support() • $checkArgu()会根据接⼝口声明验证参数
利⽤用类型判断实现overload重载
$overload() var jjQuery = $overload([String], function(selector){
return $(document.querySelectorAll(selector)); }).overload([Element.prototype],function(el){ return $(el); }).overload([HTMLCollection.prototype],function(els){ return $(els); }).overload([String,Element.prototype], function(selector, parentElement){ return $(parentElement.querySelectorAll(selector)); }).overload([/^#[^ ]*/],function(id){ return $(document.getElementById(id)); });
$overload()如何找出⽅方法 • 参数数量 • 参数的prototype • 参数的interface • 参数的类型 •
正则表达式匹配 • ⾃自定义验证函数
class和⼩小sugar们 • class和继承 • 语法sugar — keyword-like function
class和继承
None
如何实现this.base() obj.methodA ( …this.base() ) memberName记⼊入元信息 调⽤用 在原型链中逐层⽐比较 是否知道memberName 每层原型⽐比对⼀一次
找methodA所在的prototype 知道 找methodA所在的prototype 不知道
语法sugar keyword-like function
对象维护: $overwrite, $overload, $merge, $mix ! 语法糖: $fn, $run,
$dsl, $ensure ! 对象创建: $clone, $enum, $obj, $func ! ⾯面对对象: $class $interface, $support, $implement $module, $include ! 对象wrap: $methodize, $wrapper, M.$, M.$$, $, $$ ! 类型检查: $is, $check, $checkArgu, $hasProto
导出May.js的所有 keyword-like function M.exportDSL(M.global);
检查对象
$obj() 不通过constructor直接继承prototype
$overwrite() ⽅方法重写
$ensure() 吃掉错误
$enum()
May.js • 3k,源码不超过1500⾏行 • 三年,⼀一个⼈人,450多个commit • 可通过npm或者bower下载 • npm install
mayjs • bower intall mayjs • ⽂文档和测试全 • http://zhongxingdou.github.io/mayjs/
Thank you!