martintsan

martintsan 查看完整档案

上海编辑上海交通大学  |  软件工程 编辑万向区块链  |  前端开发 编辑 martintsan.com 编辑
编辑

业精于勤荒于嬉

个人动态

martintsan 回答了问题 · 3月16日

手动实现bind时为什么要用原型式继承?

先来举一个例子:

var obj = { name: "Martin" };
var hello = function(str){
    console.log("Hello " + str + ' to ' + this.name);
};
var objHello = hello.bind(obj); 

objHello('JS')

第一个问题:如果直接赋值 fBoundprototypehello 函数的 prototype 也会被修改。因此,我们需要一个中间变量 fNOP,让它等于一个空函数,通过 fNOP 来维护原型关系,并让 fBound.prototypethis.prototype 不再指向同一个原型函数。

第二个问题:我觉得应该使用 fBound 来检测,具体是将 fNOP.prototype.isPrototypeOf(this) 改成 this instanceof fBound

比如上面的代码最后改成用 new 调用

...
var newObj = new objHello('JS');

this instanceof fBound 中的 this,如果是在 new 关键字调用情况下,会指向 newObj,而 newObj 就是 fBound 的实例,this instanceof fBound 就是 true,我们不再使用 otherThis 作为 hellothis,而是直接使用 newObj 作为 hellothis;而当做普通函数调用的时候,this instanceof fBound 就是 falsehello 中的 this 依然指向 otherThis

以上,希望有所帮助 :)

关注 2 回答 2

martintsan 提出了问题 · 2018-11-22

微信更新 Patch 版本后小程序出现异常,并伴随 Fail to send sync 错误

Description

我的新安卓手机(小米 MIX3) 在其应用中心安装了微信后,有个奇怪的升级提示,升级到 Patch 版本,然后我的小程序在 P 版本上就无法运行了,通过 Remote Debug 并未发现有异常,只是手机屏幕是空白,内容无法加载,通过查看手机端调试,只是显示一句语法错误的 ERROR 但无法追踪来源。

通过各种应用的对比,目前估计是 Wepy 在某些地方对新的微信版本(Patch 版本)产生了异常,希望开发者能帮助查找原因,在此感谢开发者的辛勤付出。

Environment

  • Platform: Andriod
  • Platform version: Andriod 9
  • Wechat version: 6.7.3
  • wepy-cli version: 1.7.3
  • wepy version: 1.7.2

Reproduce

问题有些难重现,比较随机,就在我编辑这边问题的时候,它又突然好了,但完全不知道究竟怎么好的

Observed Results

wechatimg500

Expected Results

wechatimg321

Relevant Code / Logs

另外因此引发的一些相关报错信息也值得注意

wechatimg31

关注 1 回答 0

martintsan 提出了问题 · 2018-11-22

微信更新 Patch 版本后小程序出现异常,并伴随 Fail to send sync 错误

Description

我的新安卓手机(小米 MIX3) 在其应用中心安装了微信后,有个奇怪的升级提示,升级到 Patch 版本,然后我的小程序在 P 版本上就无法运行了,通过 Remote Debug 并未发现有异常,只是手机屏幕是空白,内容无法加载,通过查看手机端调试,只是显示一句语法错误的 ERROR 但无法追踪来源。

通过各种应用的对比,目前估计是 Wepy 在某些地方对新的微信版本(Patch 版本)产生了异常,希望开发者能帮助查找原因,在此感谢开发者的辛勤付出。

Environment

  • Platform: Andriod
  • Platform version: Andriod 9
  • Wechat version: 6.7.3
  • wepy-cli version: 1.7.3
  • wepy version: 1.7.2

Reproduce

问题有些难重现,比较随机,就在我编辑这边问题的时候,它又突然好了,但完全不知道究竟怎么好的

Observed Results

wechatimg500

Expected Results

wechatimg321

Relevant Code / Logs

另外因此引发的一些相关报错信息也值得注意

wechatimg31

关注 1 回答 0

martintsan 关注了问题 · 2016-10-09

angularjs中的模块加载

浏览器在加载整个html文档时遇到js中自定义的angularjs模块时会不会进行解析编译?
但在ng-app指令后会加载指定的模块,之前还需要加载解析不?求大神告知

关注 1 回答 1

martintsan 回答了问题 · 2016-10-09

angularjs中的模块加载

ng-app 是 AngularJS 1 应用的入口指令,所有内容只能在该指令所在的页面标签内运行。

关注 1 回答 1

martintsan 赞了文章 · 2016-09-14

SegmentFault 技术周刊 Vol.5 - Docker丨Build, Ship, Run, and Monitor

图片描述

啪嗒啪嗒,啪嗒啪嗒,听到后排动感十足的清脆键盘响,我就能猜到公司程序员定是被新分配了任务,进入思绪在前带路,手指跟着编程的忘我进阶,只需一会,屏幕就会出现他们华丽的诗篇。

“哟,这回被分了啥任务?”我走到天才00后旁边轻声问道,生怕分贝一高,他就走火入魔了。

“也没什么,就 70 让我实现 beta 环境容器化。”此刻的00后手指依旧飞速地敲打键盘,丝毫没有要停不下来意思。

“好了”,过了好一阵子,他转头和我说道,“以后提交代码到 gitlab,触发 webhook 将代码部署到测试服务器,就可以根据前后端不同的分支组合的域名来访问,再也不需要前后端代码都合并到 master 分支才能进行测试。

"啧啧,那 docker 用起来感觉怎么样?"我又多问了一句。
"挺方便的。"
"有没有要喷的?"我继续关心。
"不喷。"

听完00后的描述,我不禁想起了他最近洋洋洒洒写的几篇 docker 实践系列文章,既然 docker 大法如此深得人心,小编也顺带收集了社区中 docker 相关的文章,并整理为周刊。

阅读本期技术周刊,你不光能弄明白什么是 docker,使用 docker 的意义何在,还将被传授「Dockerize」秘籍,以达「build and run any app, anywhere」的境界。

What & Why?

从 docker 的官方文档开始,让初识 docker 的你形成初步的概念,感受 docker 带来的便利。

How to Dockerize?

总觉着浅浅了解不够过瘾?以下,还为你准备了基础教程和进阶教程,不光能再次巩固 docker 基础,还将切身感受 docker 的优势,将 docker 做到最大化的利用。此外,更结合容器、镜像、服务三方面内容,增强你的 docker 功力。

基础教程 - Flux7 Docker 系列教程 by 大舒

进阶教程 - Docker 实践 by Tairy

镜像、容器和服务

Build and Run Any App, Anywhere

阅读完上面的分享,对于 docker,相信你已胸有成竹了,但为达到终极目标「Build and Run Any App, Anywhere」,光有知识是不够的,那么接下来大量的实践案例,微服务、集群等相关内容,可助你在日后的实际操作中信手拈来。

Docker 实践

微服务

集群

              _ _       _                    _
__      _____| | |   __| | ___  _ __   ___  | |
\ \ /\ / / _ \ | |  / _` |/ _ \| '_ \ / _ \ | |
 \ V  V /  __/ | | | (_| | (_) | | | |  __/ |_|
  \_/\_/ \___|_|_|  \__,_|\___/|_| |_|\___| (_)
                                              
 
 
 
                        ##        .
                  ## ## ##       ==
               ## ## ## ##      ===
           /""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
           \______ o          __/
             \    \        __/
              \____\______/
 
              |          |
           __ |  __   __ | _  __   _
          /  \| /  \ /   |/  / _\ |
          \__/| \__/ \__ |\_ \__  |
 

至此,你已掌握足够的 docker 知识,就差动手了 _(ゝ「ェ:)ノ


往期周刊传送门:Vol.1 - Vue.js 起手式 | Vol.2 - 666,ES6Vol.3 - 前后端分离与前端工程化Vol.4 - 这份 Android 有点甜


# SegmentFault 技术周刊 #

「技术周刊」是社区特别推出的技术内容系列,一周一主题。周刊筛选的每篇内容,是作者的独到见解,踩坑总结和经验分享。

每周二更新,欢迎「关注」或者「订阅」。大家也可以在评论处留言自己感兴趣的主题,推荐主题相关的优秀文章。

查看原文

赞 13 收藏 75 评论 4

martintsan 回答了问题 · 2016-06-02

刚认识UML请问UML应该怎么学习?

这篇文章不错,供参考 http://m.blog.csdn.net/article/details?id=4453732

希望有所帮助~ :)

关注 13 回答 9

martintsan 回答了问题 · 2016-05-16

为什么 jQuery的html()方法不能获取tr标签?

td 要写在 tr 里,tr 要写在 table 里,恩!

关注 4 回答 3

martintsan 关注了问题 · 2016-04-01

帮我看看我写的代码有什么需要改进的,求助求助

这是一个任务清单,不知道还有什么可以改进的地方,特别是编码方式啊,帮我看看

function ToDolist(){
    this.addItem = $('#add-item');
    this.section = $('.section');
    this.list = $('.list-container .list');
    this.complateElem = $('.complate');
    this.footer = $('.section-footer');
    this.title = $('.title');  
    this.eventType = 'click';
    this.localStorage = window.localStorage;
    this.localStorageNextLength = localStorage.length;


    this.init();
}    

ToDolist.prototype = {
    init : function(){
        var This = this;
        var array = this.getAllLocalStorage();

        // console.log(array);
        // this.localStorage.clear();
        this.pushLocalStorageToDom(array);

        //    给回车按键绑定新增事项事件
        this.addItem.on('keydown', function(event){
            if(event.keyCode === 13){
                This.add();
            }
        });
        //    给销毁按钮绑定销毁事件
        this.section.delegate('.destroy', this.eventType, function(event) {
            var parentLi = $(event.currentTarget).parents('li');
            This.del(parentLi);

        });
        //    给完成按钮绑定完成事件
        this.section.delegate('.toggle', this.eventType, function(event) {
            var parentLi = $(event.currentTarget).parents('li');
            This.complate(parentLi);
    
        });
        //    给完成的事项绑定回撤事件
        this.section.delegate('.complate .toggle', this.eventType, function(event) {
            var parentLi = $(event.currentTarget).parents('li');
            This.reset(parentLi);
        });
        //    显示完成的事项
        this.title.on('click', function(){
            This.show(This.complateElem);
        });
    },
    add : function(){
        var Item = {
            "complate" : 0,
            "itemId" : ++this.localStorageNextLength,
            "addTime" : new Date().getTime(),
            "data" : this.addItem.val()
        };
    
        var json = JSON.stringify(Item);//将JSON对象转化成字符串
        this.saveTolocalStorage(json);

        var itemHtml = '<li data-id="' + this.localStorageNextLength + '">' + '<div class="view">' + '<input class="toggle" type="checkbox">' + '<label>' + Item.data + '</label>' + '<input type="button" class="destroy" value="销毁">' + '</div>' + '</li>';
        //    将拼接的事项插入到列表中,并且清空输入框
        this.list.append(itemHtml);
        this.addItem.val("");
    },
    del : function(elem){
        var localStorageId = 0;
        elem.remove();
        this.localStorageNextLength--;
        localStorageId = elem.attr('data-id');
        this.removeLocalStorageItem(localStorageId);
    },
    show : function(elem){
        if($(elem).is(':visible')){
            $(elem).hide();
        }else{
            $(elem).show();
        }
    },
    complate : function(elem){
        elem.addClass('complate');
        this.footer.find('.list').append(elem);
        var id = elem.attr('data-id');
        var data = elem.find('label').html();

        this.updataLocalStorage(id, data, "complate");
    },
    reset : function(elem){
        elem.removeClass('complate');
        this.list.append(elem);

        var id = elem.attr('data-id');
        var data = elem.find('label').html();

        this.updataLocalStorage(id, data, "reset");
    },
    saveTolocalStorage : function(json){
        this.localStorage.setItem('item' + this.localStorageNextLength, json);
    },
    getLocalStorage : function(key){
        return this.localStorage.getItem(key);
    },
    getAllLocalStorage : function(){
        var i = 0;
        var temp = null;
        var array = [];

        //    这里从1开始循环是因为存储到locaStorage的key是从1开始的
        for(var item in this.localStorage){
            temp = this.getLocalStorage(item);
            temp = JSON.parse(temp);

            if(temp){
                array.push(temp);
            }
        }
        return array;
    },
    removeLocalStorageItem : function(id){
        //////////////////////////////////////////////
        // 删除localStorage项就报错
        // console.log(id);
        this.localStorage.removeItem('item' + id);
        if(this.localStorage.length >= 1){
            this.resetLocalStorageKey(id);
        }
        
    },
    pushLocalStorageToDom : function(array){
        var i = 0;
        var len = array.length;
        var elemHtml = '';
        var complateHtml = "";
        var tempId = 0;

        for(i = 0; i < len; i++){
            if(!array[i]['complate']){
                elemHtml += '<li data-id="' + array[i].itemId + '">' + '<div class="view">' + '<input class="toggle" type="checkbox">' + '<label>' + array[i].data + '</label>' + '<input type="button" class="destroy" value="销毁">' + '</div>' + '</li>';
            }else{
                complateHtml += '<li class="complate" data-id="' + array[i].itemId + '">' + '<div class="view">' + '<input class="toggle" type="checkbox" checked="checked">' + '<label>' + array[i].data + '</label>' + '<input type="button" class="destroy" value="销毁">' + '</div>' + '</li>';
            }
        }
        this.list.append(elemHtml);
        this.footer.find('.list').append(complateHtml);
    },
    updataLocalStorage : function(id, data, type){
        type = type === 'reset' ? 0 : 1;

        var Item = {
            "complate" : type,
            "itemId" : id,
            "addTime" : new Date().getTime(),
            "data" : data
        };
        var json = JSON.stringify(Item);//将JSON对象转化成字符串
        this.localStorage.setItem('item' + id, json);
    },
    resetLocalStorageKey : function(id){
        var temp = null;
        var array = [];
        var json = null;
        
        id++;
        

        //    每次销毁事件触发时,对localStorage中的数据项key进行重排
        //    循环将后面的数据项key前移
        for(var i = id, j = i; i <= this.localStorageNextLength + 1; i++){

            j = i - 1;
            json = {};

            temp = JSON.parse(this.localStorage.getItem('item' + i));
            json.complate = temp.complate;
            json.itemId = --temp.itemId;
            json.addTime = temp.addTime;
            json.data = temp.data;
            console.log(json);
            json = JSON.stringify(json);
            
            this.localStorage.setItem("item" + j, json);
        }
        this.localStorage.removeItem("item" + (this.localStorageNextLength + 1));
        
    }
};
var toDolist = new ToDolist();

关注 7 回答 3

认证与成就

  • 获得 66 次点赞
  • 获得 6 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 6 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

注册于 2015-09-03
个人主页被 1.2k 人浏览