Git Product home page Git Product logo

blog's People

Stargazers

 avatar

Watchers

 avatar  avatar

blog's Issues

Javascript--基础--原型

Javascript--基础--原型

导语:

程序员常开的玩笑,没有对象?那就new 一个对象。 Javascript里最重要或者说最基础的概念就是对象, 但是Javascript不像Java那样靠Class 去生成一个新的对象 PS:虽然在es6等高版本中已经有了Class的关键字 但其实只是一个语法糖

关键字

  • prototype
  • constructor
  • __proto__或者说[[prototype]]

函数对象的产生

我们以最常用的function 函数对象为例子 有一个Man函数 在他的原型对象上 添加两个属性sex和eat
我们可以在Chrome控制台里打印就能看到相关信息

function Man(){
    this.name="xx"
}
Man.prototype.sex="男"
Man.prototype.eat=function(){
  console.log("wochi")
}

我们可以看到constructor的prototype 又是{sex: "n", eat: ƒ, constructor: ƒ}
不明白的同学会一直点下去发现怎么你中有我 我中有你的 无限循环
因为构造器(constructor) 本质就是一个function对象。
虽然有点绕,可以「简单」的理解为我以自己为模板构造了自己,所以我的模板(原型)就是我自己。虽然是一句废话...

我们还是用图片来讲解比较方便 易于理解

需要注意的是这里prototype 是一个对象 他是一个独立的对象 我这里的独立是指 他不是挂靠在man函数下的 如果你 var a=new Man() 然后把Man.prototype={...} 给修改了 其实a函数 还是指向的这里的object 但要注意的是如果你像在实例a里修改原型方法 比如a.proto.constructor.prototype=xxxx 那就会改动所有man函数衍生的实例切记 没搞明白别乱改

还有一些基础类型 比如字符啊 数字 布尔值 是不能改的 不提供set 只有get 简单的就讲到这里 没懂的旁友 还是自己去看书吧!

搭建NPM私服以及jenkins远程推送ssh

如何搭建NPM私服以及jenkins远程推送ssh

背景原因

公司老jenkins服务器在奔跑了4年之后,五一节后崩盘。
问题就在于因公司安全考虑只允许数据中心的机器访问外网或内网,(老jenkins机器因历史原因是一台pc机),新jenkins机器我们需要的在线编译功能被安全打回,在和运维以及安全组商议后 同意以搭建一台npm私服的形式来满足需求。

  • npm私服机器(linux) 私服拉外网包 用于被jenkins机器消费
  • jenkins机器(windows) npm registry指向npm私服 同时配置ssh和服务器连接 进行ssh推送

利用cnpm搭建npm私服

大概过程请看官方教程

1.注意bindingHost一定要注释掉 不然外网访问不到

2.数据库相关要跑起来 并且和config/index.js中的mysql配置相同
可以使用 node test/init_db来进行初始化

3.在远程ssh登录机器时记得 nohup 命令去执行cnpm项目 不然断开ssh 服务就会暂停 再进一步可以做守护进程 防止进程被关闭

jenkins搭建 注意要点

大概过程请看官网教程或谷歌 下面讲几个容易出现的问题

1.置jenkis执行脚本命令 报错 xxx不存在 是外部没装对应的环境就安装 如果外部有 那就是执行变量没有设置

 jenkins->系统管理->系统设置->添加环境变量

2.配置npm registry 指向到我们之前搭建的私服 xxx:7001

3.安装publish over ssh 插件 具体如图(网上找的) 配置完成进行test config
ssh

如果报错 - jenkins.plugins.publish_over.BapPublisherException: Failed to add SSH key. Message [invalid privatekey: TheKey]
这个错误 请使用PuttyGen 转换 具体请看 overflow的解答

在这里你需要把公钥给运维,让他帮你添加到发布服务器下。 如何生成公私钥请自行搜索

添加完成后需要在具体工程下配置 如图
ssh-config

exec command 可以是具体的代码或者脚本

到这里应该就可以发布代码了,后续可能根据不同需求还有预发、 生产不同环境的发布,但操作差不多就不多介绍了。

通过cascader分析antd源码

antd-cascader 源码分析

设计图如下

在业务开发中,根据ui提供的设计图现有的antd-cascader组件不能满足。
以此为契机,我深入antd源码,颇有收获。

同时深感大部分前端无感,抵触,无力分析 动辄上万行的大型库 故写此文写下我的一些心得和分析方法

本文较长,主要讲述如何分析大型组件库 该从哪里入手

  • 配合node_module里的代码进行查看
  • chrome-react-devtool 工具帮助我们更好的理解
  • antd版本 2.13.14
  • rc-component - 核心业务模块
  • rc-align - 定位组件-非常重要
  • rc-trigger - 交互事件核心模块

目标

  1. 加入页签的功能改变 cascader原先的排比出现
  2. 保留输入下拉菜单功能
  3. 尽量保留antd大量交互事件的功能 比如disable下的状态,比如点击区域外消失等等

思考过程

为什么不能抛开antd 完全去重新做一个组件。因为那会有非常多纰漏是无法想到的 后续观察antd源码的结果也验证了我的顾虑

核心问题

1.弹出菜单是如何定位

步骤1-分析antd-cascader
antd下有一个ts文件和编译后的js文件 我从js文件入手 在render里return的是 input 和 RcCascader 
很明显具体的核心代码在RcCascader ps:rc-xxx 是react-component的简写 antd 所有的核心都在这一级 
var input = children || React.createElement(
    'span',
    { style: style, className: pickerCls },
    React.createElement(
        'span',
        { className: prefixCls + '-picker-label' },
        this.getLabel()
    ),
    React.createElement(Input, _extends({}, .....)),
    clearIcon,
    React.createElement(Icon, { type: 'down', className: arrowCls })
);
return React.createElement(
    RcCascader,//核心代码
    _extends({}, props, { options: options, value: value, ....}),
    input //包含了input 展示value和真实value 等巧妙的切换操作
);
步骤2-分析rc-cascader
rc-cascader里有一个menus.js和cascader.js 通过文件名能猜到menus可能是默认的菜单展示component 
进去略微修改就编译就发现确实如此 因此我目标1 关联修改的就是这块内容 但是我们要先探究如何定位 就先略过。
回到cascader.js 在render里return了rcTrigger 当时看名字能猜到是事件的交互的一个包装组件 所以我们继续升入rcTrigger.js
return _react2["default"].createElement(
  _rcTrigger2["default"],
  _extends({
    ref: 'trigger'
  }, restProps, {
    ....
    popup: menus // 顾名思义 menus是作为属性传给rcTrigger的
  }),
  (0, _react.cloneElement)(children, {
    onKeyDown: this.handleKeyDown,
    tabIndex: disabled ? undefined : 0
  })
);
步骤3-分析rc-trigger
进入rc-trigger 就看到一个mixins混合类 当时很开心以为找到了包装层,仔细一看没有left,top 
就进入了误区以为是在_getContainerRenderMixin2里 结果进去看了半天发现是销毁外层container的一些逻辑 
才发现虽然是包装层 但只是最外层的用于绝对定位的定位层,具体的left top逻辑不在此处。
mixins: [(0, _getContainerRenderMixin2['default'])({
    autoMount: false,
    isVisible: function isVisible(instance) {
      return instance.state.popupVisible;
    },
    getContainer: function getContainer(instance) {
      var props = instance.props;

      var popupContainer = document.createElement('div');
      // Make sure default popup container will never cause scrollbar appearing
      // https://github.com/react-component/trigger/issues/41
      popupContainer.style.position = 'absolute';
      popupContainer.style.top = '0';
      popupContainer.style.left = '0';
      popupContainer.style.width = '100%';
      var mountNode = props.getPopupContainer ? props.getPopupContainer((0, _reactDom.findDOMNode)(instance)) : props.getDocument().body;
      mountNode.appendChild(popupContainer);
      return popupContainer;
    }
  })], 
步骤4-分析rc-trigger -> index.js
回到index 继续看render里只是返回了children就是祖传的input 没有找到关键代码 线索到这里就断了? 
所以我就仔细的一个个方法看下来 发现一个getComponent函数
还使用了props.popup这个属性(步骤2的menus) 作为子节点被包装在_Popup2['default']里 还有一些很敏感的属性 align等等 看着就有线索可寻

先看getComponent 被谁用了 很奇怪在函数内部没有找到调用的钩子 回过头来发现mixins
果然在mixins里发现调用了getComponent 所以 _Popup2['default']里有我们想要的东西

题外话 这里涉及到react组件的抽象方式 从mixins 到hoc 到render props 再到hooks 的演进 
而且我看的是编译后的代码 有很多可以学习的地方 有兴趣的可以看下来就能知道babel的一些做法
  getComponent: function getComponent() {
    var props = this.props,
    return _react2['default'].createElement(
      _Popup2['default'],
      (0, _extends3['default'])({
        action: props.action,
        align: this.getPopupAlign(),
        onAlign: props.onPopupAlign,
        animation: props.popupAnimation,
        getClassNameFromAlign: this.getPopupClassNameFromAlign
      },
      .....),
      typeof props.popup === 'function' ? props.popup() : props.popup
    );
  },
步骤5-分析rc-trigger -> popup.js -> rc-align
老规矩先看render 有this.getPopupElement() 进函数内一看return了一个rc-align包装的组件 
再进去看rc-align 根据区域判断 发现alignElement函数
  if (element) {
      result = alignElement(source, element, align);
    } else if (point) {
      result = alignPoint(source, point, align);
    }
步骤6-分析 rc-align -> alignElement -> dom-align -> align/alignElement.js
alignElement.js 依赖 align.js 和 getRegion.js
getRegion 返回一个 refNodeRegion
  offset = {
    left: _utils2['default'].getWindowScrollLeft(win),
    top: _utils2['default'].getWindowScrollTop(win)
  };
并且把这个对象 一并返回给 align 去计算
  function alignElement(el, refNode, align) {
    var target = align.target || refNode;
    var refNodeRegion = (0, _getRegion2['default'])(target);
  
    var isTargetNotOutOfVisible = !isOutOfVisibleRect(target);
  
    return (0, _align2['default'])(el, refNodeRegion, align, isTargetNotOutOfVisible);
  }

在align.js 中 doAlign 计算获取 这里就是最后的left和top 我尽然发现他用的还是kissy的核心代码

_utils2['default'].offset(source, { //
  // https://github.com/kissyteam/kissy/issues/190
  left: newElRegion.left,
  top: newElRegion.top
}, {
  useCssRight: align.useCssRight,
  useCssBottom: align.useCssBottom,
  useCssTransform: align.useCssTransform,
  ignoreShake: align.ignoreShake
});

总结

这一路走下来让我们找到了 位置计算这个核心功能的出处 而且发现是用的kissy的代码 很多新人前端估计都不知道这个库了。这是在我12年刚入行时候淘宝出的代替jquery和YUI的库。在这么多年后,又在新时代的弄潮儿react中使用了。当初看到这里真是百感交集,后续的文章会讲述我如何编写这个新的地址组件。

函数表达式和函数声明的区别

函数表达式和函数声明的区别

function Man(name){
    console.log(name)
}
var b = Man
var Man = function (a){
    console.log(1)
}
Man(2) // 1
b(3) // 3
  • 问题1 为什么b的输出还是3 而不是修改后的 1

猜测 因为 b的指针还是指向了老的Man函数体

  • 问题2 那为什么还是指向了老的函数体 或者说 老的函数体是怎么保留着的

我们都知道 变量的声明 都会提前 但是函数表达式更特殊点 他是整个函数提前 这里直接执行不会报错 就是�因为这个原因 具体可以看链接1

b = c;  
b();
console.log(a);    //1
console.log(b);    //2
console.log(c);    //3

function c() {
    a = 1, b = 2, c = 3;
};
  • 问题3 还是没有解决我们问题2的疑问老函数体的保留 别急看代码

为什么c会�报错 因为函数名在其范围内以及它的父级范围内可见 废话 我们可以理解为函数名的c 压制了 变量 c 导致他的值只有函数体内可见 所以到了外部报错

b = function c() {  
    a = 1, b = 2, c = 3, d = c;    
};

b();    
console.log(a);    //1  
console.log(b);    //2 
console.log(d);    //ƒ c() {  
                   //     a = 1, b = 2, c = 3, d = c    
                   // }  
console.log(c);    //Uncaught ReferenceError: c is not defined  

这里 b = function c(){} 的操作 我们一般是匿名函数赋值给b 这里变成了�命名�函数表达式 这个名字只在新定义的函数作用域内有效,因为规范规定了标示符不能在外围的作用域内有效:

var f = function foo(){     
    return typeof foo;    // foo是在内部作用域内有效    
};  
// foo在外部是不可见的  
typeof foo; // "undefined"  
f(); // "function"

总结

看到这里 应该能明白 问题1了

function Man(name){
    console.log(name)
}
var b = Man
相当于
var b = function Man(name){
    console.log(name)
}
可以理解为b的函数赋值其实和下面 Man函数修改没有了关系

�回到问题本身 为什么要这样写 有人会说这样不是多此一举

function Man(name){
    console.log(name)
}
var b = Man
var Man = function (a){
    console.log(1)
}

让我们来看下 monkey-patching的实践 还是�很有用的吧 有兴趣同学可以自行搜索关键字 这里就不展开了

var biugeLog = console.log;
console.log = function() {
    //在调用函数前干些什么 比如做点数据打点或者类似的 我这里就简单的alert下
    alert('改!');
    //像正常调用这个函数一样来进行调用:
    biugeLog.apply(this,arguments);
    //在这里做一些调用之后的事情。
}
console.log(1) // 打出了1 和改

参考链接

  1. https://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/
  2. https://blog.csdn.net/wy818/article/details/49247675

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.