首页

你可能不需要在 JavaScript 使用 switch 语句!

seo达人

没有 switch 就没有复杂的代码块

switch很方便:给定一个表达式,我们可以检查它是否与一堆case子句中的其他表达式匹配。 考虑以下示例:


const name = "Juliana";


switch (name) {

 case "Juliana":

   console.log("She's Juliana");

   break;

 case "Tom":

   console.log("She's not Juliana");

   break;

}

当 name 为“Juliana”时,我们将打印一条消息,并立即中断退出该块。 在switch函数内部时,直接在 case 块使用 return,就可以省略break。


当没有匹配项时,可以使用 default 选项:


const name = "Kris";


switch (name) {

 case "Juliana":

   console.log("She's Juliana");

   break;

 case "Tom":

   console.log("She's not Juliana");

   break;

 default:

   console.log("Sorry, no match");

}

switch在 Redux reducers 中也大量使用(尽管Redux Toolkit简化了样板),以避免产生大量的if。 考虑以下示例:


const LOGIN_SUCCESS = "LOGIN_SUCCESS";

const LOGIN_FAILED = "LOGIN_FAILED";


const authState = {

 token: "",

 error: "",

};


function authReducer(state = authState, action) {

 switch (action.type) {

   case LOGIN_SUCCESS:

     return { ...state, token: action.payload };

   case LOGIN_FAILED:

     return { ...state, error: action.payload };

   default:

     return state;

 }

}

这有什么问题吗?几乎没有。但是有没有更好的选择呢?


从 Python 获得的启示

来自 Telmo 的这条 Tweet引起了我的注意。 他展示了两种“switch”风格,其中一种非常接近Python中的模式。


Python 没有开关,它给我们一个更好的替代方法。 首先让我们将代码从 JavaScript 移植到Python:


LOGIN_SUCCESS = "LOGIN_SUCCESS"

LOGIN_FAILED = "LOGIN_FAILED"


auth_state = {"token": "", "error": ""}



def auth_reducer(state=auth_state, action={}):

   mapping = {

       LOGIN_SUCCESS: {**state, "token": action["payload"]},

       LOGIN_FAILED: {**state, "error": action["payload"]},

   }


   return mapping.get(action["type"], state)

在 Python 中,我们可以使用字典来模拟switch 。 dict.get() 可以用来表示 switch 的 default 语句。


当访问不存在的key时,Python 会触发一个 KeyError 错误:


>>> my_dict = {

   "name": "John",

   "city": "Rome",

   "age": 44

   }


>>> my_dict["not_here"]


# Output: KeyError: 'not_here'

.get()方法是一种更安全方法,因为它不会引发错误,并且可以为不存在的key指定默认值:


>>> my_dict = {

   "name": "John",

   "city": "Rome",

   "age": 44

   }


>>> my_dict.get("not_here", "not found")


# Output: 'not found'

因此,Pytho n中的这一行:


return mapping.get(action["type"], state)

等价于 JavaScript中的:


function authReducer(state = authState, action) {

 ...

   default:

     return state;

 ...

}

使用字典的方式替换 switch

再次思考前面的示例:


const LOGIN_SUCCESS = "LOGIN_SUCCESS";

const LOGIN_FAILED = "LOGIN_FAILED";


const authState = {

 token: "",

 error: "",

};


function authReducer(state = authState, action) {

 switch (action.type) {

   case LOGIN_SUCCESS:

     return { ...state, token: action.payload };

   case LOGIN_FAILED:

     return { ...state, error: action.payload };

   default:

     return state;

 }

}

如果不使用 switch 我们可以这样做:


function authReducer(state = authState, action) {

 const mapping = {

   [LOGIN_SUCCESS]: { ...state, token: action.payload },

   [LOGIN_FAILED]: { ...state, error: action.payload }

 };


 return mapping[action.type] || state;

}

这里我们使用 ES6 中的计算属性,此处,mapping的属性是根据两个常量即时计算的:LOGIN_SUCCESS 和 LOGIN_FAILED。

属性对应的值,我们这里使用的是对象解构,这里 ES9((ECMAScript 2018)) 出来的。


const mapping = {

 [LOGIN_SUCCESS]: { ...state, token: action.payload },

 [LOGIN_FAILED]: { ...state, error: action.payload }

}

你如何看待这种方法?它对 switch 来说可能还能一些限制,但对于 reducer 来说可能是一种更好的方案。


但是,此代码的性能如何?


性能怎么样?

switch 的性能优于字典的写法。我们可以使用下面的事例测试一下:


console.time("sample");

for (let i = 0; i < 2000000; i++) {

 const nextState = authReducer(authState, {

   type: LOGIN_SUCCESS,

   payload: "some_token"

 });

}

console.timeEnd("sample");

测量它们十次左右,


for t in {1..10}; do node switch.js >> switch.txt;done

for t in {1..10}; do node map.js >> map.txt;done

clipboard.png


人才们的 【三连】 就是小智不断分享的最大动力,如果本篇博客有任何错误和建议,欢迎人才们留言,最后,谢谢大家的观看。


原文:https://codeburst.io/alternat...


代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务



使用 VSCode 开发 Gatsby 项目配置

seo达人

初始化

使用 https://github.com/XYShaoKang... 作为基础模板

gatsby new gatsby-project-config https://github.com/XYShaoKang/gatsby-hello-world

Prettier 配置

安装 VSCode 扩展

按 Ctrl + P (MAC 下: Cmd + P) 输入以下命令,按回车安装


ext install esbenp.prettier-vscode

安装依赖

yarn add -D prettier

Prettier 配置文件.prettierrc.js

// .prettierrc.js

module.exports = {

 trailingComma: 'es5',

 tabWidth: 2,

 semi: false,

 singleQuote: true,

 endOfLine: 'lf',

 printWidth: 50,

 arrowParens: 'avoid',

}

ESLint 配置

安装 VSCode 扩展

按 Ctrl + P (MAC 下: Cmd + P) 输入以下命令,按回车安装


ext install dbaeumer.vscode-eslint

安装 ESLint 依赖

yarn add -D eslint babel-eslint eslint-config-google eslint-plugin-react eslint-plugin-filenames

ESLint 配置文件.eslintrc.js

使用官方仓库的配置,之后在根据需要修改


// https://github.com/gatsbyjs/gatsby/blob/master/.eslintrc.js

// .eslintrc.js

module.exports = {

 parser: 'babel-eslint',

 extends: [

   'google',

   'eslint:recommended',

   'plugin:react/recommended',

 ],

 plugins: ['react', 'filenames'],

 parserOptions: {

   ecmaVersion: 2016,

   sourceType: 'module',

   ecmaFeatures: {

     jsx: true,

   },

 },

 env: {

   browser: true,

   es6: true,

   node: true,

   jest: true,

 },

 globals: {

   before: true,

   after: true,

   spyOn: true,

   __PATH_PREFIX__: true,

   __BASE_PATH__: true,

   __ASSET_PREFIX__: true,

 },

 rules: {

   'arrow-body-style': [

     'error',

     'as-needed',

     { requireReturnForObjectLiteral: true },

   ],

   'no-unused-expressions': [

     'error',

     {

       allowTaggedTemplates: true,

     },

   ],

   'consistent-return': ['error'],

   'filenames/match-regex': [

     'error',

     '^[a-z-\\d\\.]+$',

     true,

   ],

   'no-console': 'off',

   'no-inner-declarations': 'off',

   quotes: ['error', 'backtick'],

   'react/display-name': 'off',

   'react/jsx-key': 'warn',

   'react/no-unescaped-entities': 'off',

   'react/prop-types': 'off',

   'require-jsdoc': 'off',

   'valid-jsdoc': 'off',

 },

 settings: {

   react: {

     version: '16.4.2',

   },

 },

}

解决 Prettier ESLint 规则冲突

推荐配置


安装依赖


yarn add -D eslint-config-prettier eslint-plugin-prettier

在.eslintrc.js中的extends添加'plugin:prettier/recommended'


module.exports = {

 extends: ['plugin:prettier/recommended'],

}

VSCode 中 Prettier 和 ESLint 协作

方式一:使用 ESLint 扩展来格式化代码

配置.vscode/settings.json


// .vscode/settings.json

{

 "eslint.format.enable": true,

 "[javascript]": {

   "editor.defaultFormatter": "dbaeumer.vscode-eslint"

 },

 "[javascriptreact]": {

   "editor.defaultFormatter": "dbaeumer.vscode-eslint"

 }

}

ESLint 扩展会默认忽略.开头的文件,比如.eslintrc.js

如果需要格式化.开头的文件,可以在.eslintignore中添加一个否定忽略来启用对应文件的格式化功能.


!.eslintrc.js

或者直接使用!.*,这样可以开启所有点文件的格式化功能


方式二:使用 Prettier 扩展来格式化代码

在版prettier-vscode@v5.0.0中已经删除了直接对linter的集成,所以版没法像之前那样,通过prettier-eslint来集成ESLint的修复了(一定要这样用的话,可以通过降级到prettier-vscode@4来使用了).如果要使用Prettier来格式化的话,就只能按照官方指南中的说的集成方法,让Prettier来处理格式,通过配置在保存时使用ESlint自动修复代码.只是这样必须要保存文件时,才能触发ESLint的修复了.


配置 VSCode 使用 Prettier 来格式化 js 和 jsx 文件

在项目中新建文件.vscode/settings.json


// .vscode/settings.json

{

 "[javascript]": {

   "editor.defaultFormatter": "esbenp.prettier-vscode"

 },

 "[javascriptreact]": {

   "editor.defaultFormatter": "esbenp.prettier-vscode"

 },

 "editor.codeActionsOnSave": {

   "source.fixAll.eslint": true

 }

}

说实话这个体验很糟糕,之前直接一键格式化代码并且修复 ESLint 错误,可以对比格式化之前和格式化之后的代码,如果感觉不对可以直接撤销更改就好了.现在必须要通过保存,才能触发修复 ESlint 错误.而在开发过程中,通过监听文件改变来触发热加载或者重新编译是很常见的操作.这样之后每次想要去修复 ESLint 错误,还是只是想看看修复错误之后的样子,都必须要去触发热加载或重新编译,每次操作的成本就太高了.

我更推荐第一种方式使用 ESLint 扩展来对代码进行格式化.


调试 Gatsby 配置

调试构建过程

添加配置文件.vscode/launch.json


// .vscode/launch.json

{

 // 使用 IntelliSense 了解相关属性。

 // 悬停以查看现有属性的描述。

 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387

 "version": "0.2.0",

 "configurations": [

   {

     "name": "Gatsby develop",

     "type": "node",

     "request": "launch",

     "protocol": "inspector",

     "program": "${workspaceRoot}/node_modules/gatsby/dist/bin/gatsby",

     "args": ["develop"],

     "stopOnEntry": false,

     "runtimeArgs": ["--nolazy"],

     "sourceMaps": false,

     "outputCapture": "std"

   }

 ]

}

的gatsby@2.22.*版本中调试不能进到断点,解决办法是降级到2.21.*,yarn add gatsby@2.21.40,等待官方修复再使用版本的

调试客户端

需要安装 Debugger for Chrome 扩展


ext install msjsdiag.debugger-for-chrome

添加配置文件.vscode/launch.json


// .vscode/launch.json

{

 // 使用 IntelliSense 了解相关属性。

 // 悬停以查看现有属性的描述。

 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387

 "version": "0.2.0",

 "configurations": [

   {

     "type": "chrome",

     "request": "launch",

     "name": "Gatsby Client Debug",

     "url": "http://localhost:8000",

     "webRoot": "${workspaceFolder}"

   }

 ]

}

先启动 Gatsby,yarn develop,然后按 F5 开始调试.

使用 vue 1.0.3 $set 函数遇到的坑

seo达人

vue 1.0.3  中 $set 函数是动态改变或添加一个 data 中的属性值时 属性 key 不可以使用纯数字。



例如:



var app = new Vue({

     el:"#app",

     data:{

         test:{

             k1:'v1',

             k2:'v2'

         }

     },

     methods:{

         changeTestValue:function{

             // 动态改变 test 中某一属性的值

             var key = 'test.k1';  // 改变 test 属性中的 k1 的值

             this.$set(key,'changev1');  // 此处执行没有问题

            // 改变 整个 test 的值可以使用

            this.$set('test',{k1:'change-demo-v1',k2:'change-demo-v2'});   // 此处执行没有问题

            // 动态给 test 增加一个属性  k3

            this.$set('test.k3','test-add-value3');   // 此处执行没有问题

 

 

            // 此处有坑 当你的 属性为全数字的时候,则 函数无效,不报错,但是也添加不上值。

            // 例如

            this.$set('test.123','test-add-123');  // 此处执行不报错,但是也没有效果。

 

 

            // 所以在使用老版本vue的时候尽量避免 属性 key 未纯数字,或其他特殊字符。

         }

     }

});



除了这个坑以外还有另外一个坑,不过没有具体试验,

watch 监听某一值得变化,好像有点问题, 实际结果是只要 data 中的任意一个值发生变化都会被捕捉到。







最后还是使用 vue 2.x  以上版本吧,bug 少很多。







另外 $set 函数在2.x 中使用方式有所变化。







this.$set(target,key,obj);



target 对象类型,是需要赋值或修改的对象,



key  是字符串类型, 是 target 对象的属性



obj  可以是字符串,可以是对象类型,是 你要修改的或增加的值


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

日历

链接

blogger

蓝蓝 http://www.lanlanwork.com

存档