马上就春节了,今天2月11日,能不能在7天里学上1门新技术?试试看哦。

先来个简短的自我介绍:奔四的人了,工作十年,现在还做开发。喜欢各种新技术,热爱学习,水平平平(哈哈)。去年的春节写码中度过,今年打算做点有意思的事情。7天时间可以学点啥,抛去吃饭聚会和唠嗑,有可能学一门新技术吗?试试看哦。

背景:一直主要做后端,用过C/Java/C#。想要挑战一下Web必会的语言,JavaScript。

就这么开始了,每天更新。

7 2 收藏


直接登录
最新评论
  • 唐尤华 just programmer 02/12

    2月12日

    技术是拿来解决问题的。JavaScript可以解决微信小程序开发的问题,前端在webview上运行,后端在node.js上运行。

    学习JavaScript春节7天乐:定好目标(出什么结果),行动【看懂(不会的语法记下来),能运行,会修改】,总结(学习不会的内容)。

    定好目标:能够把微信小程序解决方案JavaScript部分看懂(复制粘贴),能运行,会修改(改改更健康)

    行动:先看README,少走弯路。一共看3个README,解决方案、client、server。

    看不懂的:
    – require
    – module.exports
    – login({这里写的是什么})
    – webSocket
    – tunnel.on/tunnel.emit(on,emit是什么)
    – ()=>
    – console.log/console.error
    – new

    看不懂的分类:文件拆分,一个SDK那么大,要拆分引用;函数回调,调用了API要处理返回结果,用了回调函数?;对象、函数、一些琐碎的语法。

    试了好几样,发现过于复杂。
    找到一个简单的学习方法,安装Node.js,把文档的例子运行一遍。
    把看不懂的点,在node上跑一下。

  • 唐尤华 just programmer 02/13

    2月13日
    整理小程序Client JavaScript实现的功能,看这些功能的JavaScript实现,在Node.js环境下运行,掌握不理解的用法(是什么?怎么用?自己实现会怎么写?为什么示例要这么写?)。

    看不懂的:
    – require
    – module.exports
    – login({这里写的是什么})
    – webSocket
    – tunnel.on/tunnel.emit(on,emit是什么)
    – ()=>
    – console.log/console.error
    – new

  • 唐尤华 just programmer 02/14

    2月14日
    马上就要奔上火车了,这个时候需要离线的环境加上离线的文档,继续学习。
    恰好,Node.js可以满足这些要求。
    遇到不懂的JavaScript语法怎么查呢,恩,还是需要有参考的手册。
    电子版的ECMA标准pdf也已经备好了。
    么么哒,一路学起来。

    临出发win10崩溃了,还好可以切换到mac,继续在mac上撸代码。

  • 唐尤华 just programmer 02/15

    2月15日

    在车站把module.require的内容过了一遍。JavaScript确实强大,比起早年接触的时候强大了许多。

    用dash里面JavaScript和node文档,搜索require关键字。对语法和语义给出了详细的解释。包括不限于,基本用法,module是什么,require中的path如何处理绝对路径,相对路径,文件链接,文件格式(文本/.js/json/二进制)。如何处理不同版本以及循环引用问题。

    验证例子用了node.js,编写示例然后 node bar.js执行看结果。

    借助这个语法,可以方便地组织项目代码(不用所有功能写在同一个文件里)。微信小程序的client正是这么处理的。今天就着这个知识点把client的js代码梳理一下。

  • 唐尤华 just programmer 02/16

    2月16日

    # wafer2-client-sdk的代码组织
    整个代码是由index.js与lib/的子功能分别实现的:
    – index.js
    – lib
    – login.js 登录

    通过module.exports导出模块,lib模块=>sdk模块

    这里遇到一个看不懂的,这个LoginError用了prototype,注释里说明是异常类
    var LoginError = (function() {}
    function LoginError(type, message) {
    Error.call(this, message);
    this.type = type;
    this.message = message;
    }

    LoginError.prototype = new Error();
    LoginError.prototype.contructor = LoginError;

    return LoginError;
    })();

    用Error自定义了登录错误信息,标记了错误类型,以及错误消息。
    这里用到了对Error的扩展,增加了type和message属性。
    type在consts.js中定义,在整个处理流程中非常重要,给出了每一步的错误原因和详细信息。

    在调试过程中,一直以为自己写错了代码。
    其实是在捕获异常后,console.log或console.error会直接打印error栈。
    如果要输出对应的内容,需要这么写:

    var error = new LoginError(‘code’, ‘message’);
    console.error(`${error.type} : ${error.message}`);

    这里面还牵扯到了错误信息的返回处理,在方法中定义success和fail,处理返回结果。

  • 唐尤华 just programmer 02/17

    2月17日

    # 导出全局配置config.js

    与constants类似,小程序中还有一些全局配置:
    host: 后台主机名
    loginUrl: 登录API
    requestUrl: 请求API
    tunnelUrl: 信道服务器API
    uploadUrl: 上传图片API

    使用module.exports导出
    在配置的过程中,可以使用字符串模板Template Literal `${varName}`,类似其他语言的format string

    通过这样的配置分离,实现了配置分离,更好地适应开发需要:比如切换生产环境与开发环境。
    这里需要注意的是:URL一定要把https://加上,否则小程序request时不会识别。

    这里有一个疑惑:module.exports与exports的区别和相同点在哪里?

    # 导出常量constants.js

    在constants中定义对象,名称和值,用module.exports导出。
    在SDK中引入constants,用Object.keys方法遍历对象中的属性,用exports[key]导出。
    这样可以在SDK引入的地方直接调用。

    console.log(mysdk.MY_CONST);

    在wafer的SDK中,定义的常量,有
    – session中的几个关键常量,code, encryptedData, iv, id, skey
    – magicId? 这个东东不知道是干啥用的
    – 错误信息,包括
    – invalid params: 参数错误
    – login failed: 登录失败
    – get user info: 获取用户信息失败
    – login timeout: 登录超时
    – login failed: 登录失败
    – login session not received: session获取失败

    # 扩展对象utils.js

    options = utils.extend({}, defaultOptions, options);

    这句在login方法中调用了,看起来是对默认的options进行了扩展,但是不明白道理。

    exports.extend = function extend(target) {
    var sources = Array.prototype.slice.call(arguments, 1);

    for (var i = 0; i < sources.length; i += 1) {
    var source = sources[i];
    for (var key in source) {
    if (source.hasOwnProperty(key)) {
    target[key] = source[key];
    }
    }
    }

    return target;
    };

    utils.js这个定义让人比较费解。

    于是,自己编写方法进行测试。实验下来的效果,确实给options增加了方法,defaultOptions中的函数。

    再仔细查看一下,发现login中的options这种用法是为了避免未定义success, fail方法做的预防异常处理:

    var noop = function noop() {};
    var defaultOptions = {
    method: ‘GET’,
    success: noop,
    fail: noop,
    loginUrl: null,
    };

    options = utils.extend({}, defaultOptions, options);

    method, success和fail给出了默认实现。
    如果options有相同的定义,用options中的定义覆盖,否则套用defaultOptions中的定义。

    这里有一个问题: 究竟是如何做到的呢,比如在options中定义了自己的success方法,method指定为POST,如何确保使用我的定义呢?
    猜想之下,最合理的做法就是检查里面的名字,如果发现options中有了自己的定义就进行替换。

    查看extend方法定义,确实如此:
    if (source.hasOwnProperty(key)) {
    target[key] = source[key];
    }

    这里用到了Object.prototype.hasOwenProperty,判断是否包含该属性。

    接下来就是 Array.prototype.slice.call 这句话的理解。
    这句把传入的对象组成了数组,var sources = Array.prototype.slice.call(arguments, 1);
    从index=1(传入的第2个元素开始,提取为数组)
    例如: 传入[1,2,3],取到的是[2,3]
    ({}, defaultOptions, options)
    取到的就是[defaultOptions, options],接着遍历,后面的属性会替换前面的属性

    总结: utils.js中的extends方法为调用提供了默认参数,extends调用后会覆盖默认值(属性与方法)。
    – session invalid: session无效
    – check login failed: 检查登录失败

  • 唐尤华 just programmer 6 天前

    2月18日

    # function callback
    var getWxLoginResult = function getLoginCode(callback)

    callback(…) // 回调

    把函数作为参数传入,可以进行回调。

    // 成功回调
    var callSuccess = function () {
    success.apply(null, arguments);
    complete.apply(null, arguments);
    };

    // 失败回调
    var callFail = function (error) {
    fail.call(null, error);
    complete.call(null, error);
    };

    这里apply和call的区别?

    # prototype.call
    在之前的自定义Error中,通过Error.call(this, arg)实现了构造函数调用。

    var LoginError = (function () {
    function LoginError(type, message) {
    Error.call(this, message);
    this.type = type;
    this.message = message;
    }

    LoginError.prototype = new Error();
    LoginError.prototype.constructor = LoginError;

    return LoginError;
    })();

    LoginError本身是一个匿名函数,prototype定义为Error,构造函数是LoginError(type, message)
    prototype.constructor = LoginError; // 指定了Function LoginError的constructor
    在构造函数中,Error.call(this, message) // 调用Error构造函数,this指的LoginError
    prototype.call可以调用匿名函数。

    myfunc.call(obj); // 在myfunc中this即obj
    # function object
    JavaScript每个function都是一个function对象。
    每个函数都有返回值,默认返回undefined,也可以自己返回定义的值。

    函数传递参数arguments,默认是值传递。
    如果arguments传入的是对象引用,函数内对对象修改,作用域会扩大到函数外部。

    匿名方法anonymous function,函数的名字可以不写。
    函数带名字,在出现错误时可以方便地定位到错误的函数。

    函数表达式function expression,可以不写function关键字定义一个函数。
    这里应用了IIFE(immediately invokable function expression)模式。
    (function(){
    console.log(‘This is a function expression’);
    })();
    IIFE一旦声明就会立即执行。

    箭头函数arrow function,适合non-method function,不能用作constructor
    (arg) => { console.log(`This is an arrow function with param ${arg}`)};

    注意:这里引发了一个this关键字问题
    每个函数中都有this变量,但是在函数中调用时含义会有所不同,不可嵌套。
    解决这个问题可以这么做:

    function wrapperFunc() {
    var that = this;
    that.val = 1;

    setInterval(function growUp() {
    that.val++;
    }, 1000);

    }

    然而,箭头函数没有this关键字,可以这么干:

    function wrapperFunc() {
    this.val = 1;

    setInterval(()=>{
    this.val++;
    }, 1000);
    }

    # typeof, throw, 默认属性

    typeof判断类型,JavaScript支持的类型有:
    object
    number
    function
    string

    throw Error(…) 抛出错误,通过 try…catch 捕获异常
    在request.js中自定义了RequestError,为Error增加了type属性
    捕获后可查看e.type, e.message

    var success = options.success || noop;
    默认属性,如果没有定义success,会采用noop定义的空方法。

    在request.js中,默认属性方法做了以下功能:
    从session里读取会话服务器发送的Session,request请求时,把session信息附加到request请求。
    wx.request(utils.extend({}, options, {
    header: utils.extend({}, originHeader, authHeader),…

  • 唐尤华 just programmer 5 天前

    2月19日

    截止今天已经7天了,过年7天乐结束。是时候总结一下这7天的成果啦。后端开发者学习JavaScript的7天之旅。