当我们重构使用 var
的老代码时,一定要注意这种变化。盲目使用 let
替换 var
后可能会导致预期意外的结果。
注意:
let
和const
是块级作用域语句。所以在语句块以外引用这些变量时,会造成引用错误ReferenceError
。
console.log(x); let x = 'hi'; // ReferenceError: x is not defined
-
1
-
2
-
3
最佳实践: 在重构老代码时,
var
声明需要格外的注意。在创建一个新项目时,使用let
声明一个变量,使用const
来声明一个不可改变的常量。
(回到目录)
Replacing IIFEs with Blocks
我们以往创建一个 立即执行函数 时,一般是在函数最外层包裹一层括号。
ES6支持块级作用域(更贴近其他语言),我们现在可以通过创建一个代码块(Block)来实现,不必通过创建一个函数来实现,
(function () { var food = 'Meow Mix'; }()); console.log(food); // Reference Error
-
1
-
2
-
3
-
4
-
5
使用支持块级作用域的ES6的版本:
{ let food = 'Meow Mix'; } console.log(food); // Reference Error
-
1
-
2
-
3
-
4
-
5
(回到目录)
Arrow Functions
一些时候,我们在函数嵌套中需要访问上下文中的 this
。比如下面的例子:
function Person(name) { this.name = name; } Person.prototype.prefixName = function (arr) { return arr.map(function (character) { return this.name + character; // Cannot read property 'name' of undefined }); };
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
一种通用的方式是把上下文中的 this
保存在一个变量里:
function Person(name) { this.name = name; } Person.prototype.prefixName = function (arr) { var that = this; // Store the context of this return arr.map(function (character) { return that.name + character; }); };
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
我们也可以把 this
通过属性传进去:
function Person(name) { this.name = name; } Person.prototype.prefixName = function (arr) { return arr.map(function (character) { return this.name + character; }, this); };
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
还可以直接使用 bind
:
function Person(name) { this.name = name; } Person.prototype.prefixName = function (arr) { return arr.map(function (character) { return this.name + character; }.bind(this)); };
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
使用 箭头函数,this
的值不用我们再做如上几段代码的特殊处理,直接使用即可。
上面的代码可以重写为下面这样:
function Person(name) { this.name = name; } Person.prototype.prefixName = function (arr) { return arr.map(character => this.name + character); };
-
1
-
2
-
3
-
4
-
5
-
6
-
7
最佳实践:使用箭头函数,再也不用考虑
this
的问题了。
当我们编写只返回一个表达式值的简单函数时,也可以使用箭头函数,如下:
var squares = arr.map(function (x) { return x * x }); // Function Expression
- 1
const arr = [1, 2, 3, 4, 5]; const squares = arr.map(x => x * x); // Arrow Function for terser implementation
-
1
-
2
最佳实践:尽可能地多使用 箭头函数。
(回到目录)
Strings
在ES6中,标准库也被同样增强了,像字符串对象就新增了 .includes()
和 .repeat()
方法。
.includes( )
var string = 'food'; var substring = 'foo'; console.log(string.indexOf(substring) > -1);
-
1
-
2
-
3
-
4
现在,我们可以使用 .inclues()
方法,替代以往判断内容 > -1
的方式。
.includes()
方法会极简地返回一个布尔值结果。
const string = 'food'; const substring = 'foo'; console.log(string.includes(substring)); // true
-
1
-
2
-
3
-
4
.repeat( )
function repeat(string, count) { var strings = []; while(strings.length < count) { strings.push(string); } return strings.join(''); }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
在ES6中,我们可以使用一个极简的方法来实现重复字符:
// String.repeat(numberOfRepetitions) 'meow'.repeat(3); // 'meowmeowmeow'
-
1
-
2
Template Literals
使用 字符串模板字面量,我可以在字符串中直接使用特殊字符,而不用转义。
var text = "This string contains \"double quotes\" which are escaped.";
- 1
let text = `This string contains "double quotes" which don't need to be escaped anymore.`;
- 1
字符串模板字面量 还支持直接插入变量,可以实现字符串与变量的直接连接输出。
var name = 'Tiger'; var age = 13; console.log('My cat is named ' + name + ' and is ' + age + ' years old.');
-
1
-
2
-
3
-
4
更简单的版本:
const name = 'Tiger'; const age = 13; console.log(`My cat is named ${name} and is ${age} years old.`);
-
1
-
2
-
3
-
4
ES5中,我们要这样生成多行文本:
var text = ( 'cat\n' + 'dog\n' + 'nickelodeon' );
-
1
-
2
-
3
-
4
-
5
或者:
var text = [ 'cat', 'dog', 'nickelodeon' ].join('\n');
-
1
-
2
-
3
-
4
-
5
字符串模板字面量 让我们不必特别关注多行字符串中的换行转义符号,直接换行即可:
let text = ( `cat dog nickelodeon` );
-
1
-
2
-
3
-
4
字符串模板字面量 内部可以使用表达式,像这样:
let today = new Date(); let text = `The time and date is ${today.toLocaleString()}`;
-
1
-
2
(回到目录)
Destructuring
解构让我们可以使用非常便捷的语法,直接将数组或者对象中的值直接分别导出到多个变量中,
Destructuring Arrays
解构数组
var arr = [1, 2, 3, 4]; var a = arr[0]; var b = arr[1]; var c = arr[2]; var d = arr[3];
-
1
-
2
-
3
-
4
-
5
let [a, b, c, d] = [1, 2, 3, 4]; console.log(a); // 1 console.log(b); // 2
-
1
-
2
-
3
-
4
Destructuring Objects
解构对象
var luke = { occupation: 'jedi', father: 'anakin' }; var occupation = luke.occupation; // 'jedi' var father = luke.father; // 'anakin'
-
1
-
2
-
3
let luke = { occupation: 'jedi', father: 'anakin' }; let {occupation, father} = luke; console.log(occupation); // 'jedi' console.log(father); // 'anakin'
-
1
-
2
-
3
-
4
-
5
(回到目录)
Modules
ES6之前,浏览器端的模块化代码,我们使用像Browserify这样的库,
在 Node.js 中,我们则使用 require。
在ES6中,我们现在可以直接使用AMD 和 CommonJS这些模块了。
Exporting in CommonJS
module.exports = 1; module.exports = { foo: 'bar' }; module.exports = ['foo', 'bar']; module.exports = function bar () {};
-
1
-
2
-
3
-
4
Exporting in ES6
在ES6中,提供了多种设置模块出口的方式,比如我们要导出一个变量,那么使用 变量名 :
export let name = 'David'; export let age = 25;
-
1
-
2
还可以为对象 导出一个列表:
function sumTwo(a, b) { return a + b; } function sumThree(a, b, c) { return a + b + c; } export { sumTwo, sumThree };
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
我们也可以使用简单的一个 export
关键字来导出一个结果值:
export function sumTwo(a, b) { return a + b; } export function sumThree(a, b, c) { return a + b + c; }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
最后,我们可以 导出一个默认出口:
function sumTwo(a, b) { return a + b; } function sumThree(a, b, c) { return a + b + c; } let api = { sumTwo, sumThree }; export default api;
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
最佳实践:总是在模块的 最后 使用
export default
方法。
它让模块的出口更清晰明了,节省了阅读整个模块来寻找出口的时间。
更多的是,在大量CommonJS模块中,通用的习惯是设置一个出口值或者出口对象。
最受这个规则,可以让我们的代码更易读,且更方便的联合使用CommonJS和ES6模块。
Importing in ES6
ES6提供了好几种模块的导入方式。我们可以单独引入一个文件:
import 'underscore';
- 1
这里需要注意的是, 整个文件的引入方式会执行该文件内的最上层代码。
就像Python一样,我们还可以命名引用:
import { sumTwo, sumThree } from 'math/addition';
- 1
我们甚至可以使用 as
给这些模块重命名:
import { sumTwo as addTwoNumbers, sumThree as sumThreeNumbers } from 'math/addition';
-
1
-
2
-
3
-
4
另外,我们能 引入所有的东西(原文:import all the things) (也称为命名空间引入)
import * as util from 'math/addition';
- 1
最后,我们能可以从一个模块的众多值中引入一个列表:
import * as additionUtil from 'math/addtion'; const { sumTwo, sumThree } = additionUtil;
-
1
-
2
像这样引用默认对象:
import api from 'math/addition'; // Same as: import { default as api } from 'math/addition';
-
1
-
2
我们建议一个模块导出的值应该越简洁越好,不过有时候有必要的话命名引用和默认引用可以混着用。如果一个模块是这样导出的:
// foos.js export { foo as default, foo1, foo2 };
-
1
-
2
那我们可以如此导入这个模块的值:
import foo, { foo1, foo2 } from 'foos';
- 1
我们还可以导入commonjs模块,例如React:
import React from 'react'; const { Component, PropTypes } = React;
-
1
-
2
更简化版本:
import React, { Component, PropTypes } from 'react';
- 1
注意:被导出的值是被 绑定的(原文:bingdings),而不是引用。
所以,改变一个模块中的值的话,会影响其他引用本模块的代码,一定要避免此种改动发生。
(回到目录)
Parameters
在ES5中,许多种方法来处理函数的 参数默认值(default values),参数数量(indefinite arguments),参数命名(named parameters)。
ES6中,我们可以使用非常简洁的语法来处理上面提到的集中情况。
Default Parameters
function addTwoNumbers(x, y) { x = x || 0; y = y || 0; return x + y; }
-
1
-
2
-
3
-
4
-
5
ES6中,我们可以简单为函数参数启用默认值:
function addTwoNumbers(x=0, y=0) { return x + y; }
-
1
-
2
-
3
addTwoNumbers(2, 4); // 6 addTwoNumbers(2); // 2 addTwoNumbers(); // 0
-
1
-
2
-
3
Rest Parameters
ES5中,遇到参数数量不确定时,我们只能如此处理:
function logArguments() { for (var i=0; i < arguments.length; i++) { console.log(arguments[i]); } }
-
1
-
2
-
3
-
4
-
5
使用 rest 操作符,我们可以给函数传入一个不确定数量的参数列表:
function logArguments(...args) { for (let arg of args) { console.log(arg); } }
-
1
-
2
-
3
-
4
-
5
Named Parameters
命名函数
ES5中,当我们要处理多个 命名参数 时,通常会传入一个 选项对象 的方式,这种方式被jQuery采用。
function initializeCanvas(options) { var height = options.height || 600; var width = options.width || 400; var lineStroke = options.lineStroke || 'black'; }
-
1
-
2
-
3
-
4
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
文末
初级工程师拿到需求会直接开始做,然后做着做着发现有问题了,要么技术实现不了,要么逻辑有问题。
而高级工程师拿到需求会考虑很多,技术的可行性?对现有业务有没有帮助?对现有技术架构的影响?扩展性如何?等等…之后才会再进行设计编码阶段。
而现在随着跨平台开发,混合式开发,前端开发之类的热门,Android开发者需要学习和掌握的技术也在不断的增加。
通过和一些行业里的朋友交流讨论,以及参考现在大厂面试的要求。我们花了差不多一个月时间整理出了这份Android高级工程师需要掌握的所有知识体系。你可以看下掌握了多少。
混合式开发,微信小程序。都是得学会并且熟练的
这些是Android相关技术的内核,还有Java进阶
高级进阶必备的一些技术。像移动开发架构项目实战等
Android前沿技术;包括了组件化,热升级和热修复,以及各种架构跟框架的详细技术体系
以上即是我们整理的Android高级工程师需要掌握的技术体系了。可能很多朋友觉得很多技术自己都会了,只是一些新的技术不清楚而已。应该没什么太大的问题。
而这恰恰是问题所在!为什么别人高级工程师能年限突破30万,而你只有十几万呢?
就因为你只需补充你自己认为需要的,但并不知道企业需要的。这个就特别容易造成差距。因为你的技术体系并不系统,是零碎的,散乱的。那么你凭什么突破30万年薪呢?
我这些话比较直接,可能会戳到一些人的玻璃心,但是我知道肯定会对一些人起到点醒的效果的。而但凡只要有人因为我的这份高级系统大纲以及这些话找到了方向,并且付出行动去提升自我,为了成功变得更加努力。那么我做的这些就都有了意义。
喜欢的话请帮忙转发点赞一下能让更多有需要的人看到吧。谢谢!
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
2-1712718784434)]
[外链图片转存中…(img-3Ys2K6SE-1712718784434)]
[外链图片转存中…(img-EzAkGOHM-1712718784435)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-oeu8ObBW-1712718784435)]
文末
初级工程师拿到需求会直接开始做,然后做着做着发现有问题了,要么技术实现不了,要么逻辑有问题。
而高级工程师拿到需求会考虑很多,技术的可行性?对现有业务有没有帮助?对现有技术架构的影响?扩展性如何?等等…之后才会再进行设计编码阶段。
而现在随着跨平台开发,混合式开发,前端开发之类的热门,Android开发者需要学习和掌握的技术也在不断的增加。
通过和一些行业里的朋友交流讨论,以及参考现在大厂面试的要求。我们花了差不多一个月时间整理出了这份Android高级工程师需要掌握的所有知识体系。你可以看下掌握了多少。
混合式开发,微信小程序。都是得学会并且熟练的
[外链图片转存中…(img-wi6KULhq-1712718784435)]
这些是Android相关技术的内核,还有Java进阶
[外链图片转存中…(img-ZulgfYad-1712718784436)]
高级进阶必备的一些技术。像移动开发架构项目实战等
[外链图片转存中…(img-WftseRlZ-1712718784436)]
Android前沿技术;包括了组件化,热升级和热修复,以及各种架构跟框架的详细技术体系
[外链图片转存中…(img-sNOfkp8K-1712718784436)]
以上即是我们整理的Android高级工程师需要掌握的技术体系了。可能很多朋友觉得很多技术自己都会了,只是一些新的技术不清楚而已。应该没什么太大的问题。
而这恰恰是问题所在!为什么别人高级工程师能年限突破30万,而你只有十几万呢?
就因为你只需补充你自己认为需要的,但并不知道企业需要的。这个就特别容易造成差距。因为你的技术体系并不系统,是零碎的,散乱的。那么你凭什么突破30万年薪呢?
我这些话比较直接,可能会戳到一些人的玻璃心,但是我知道肯定会对一些人起到点醒的效果的。而但凡只要有人因为我的这份高级系统大纲以及这些话找到了方向,并且付出行动去提升自我,为了成功变得更加努力。那么我做的这些就都有了意义。
喜欢的话请帮忙转发点赞一下能让更多有需要的人看到吧。谢谢!
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-jVc9gnzu-1712718784437)]