前端日常开发必背知识点

写在前面:

今年从春招到秋招面试了国内所谓的BAT、TMD等互联网企业前端开发。各大公司的面试风格可谓各有千秋,从编程基础、框架原理到算法、网络再到对新技术(比如PWA)的认知地考核,其中尤其以前端基础JS编程为考核重点,各大公司对此地看重程度已经到了一言不合就"丢算法撸代码"的地步。而小编在笔试机试这样的编码过程中居然一时忘掉了部分基本操作,结果不言而喻,就好比打野忘了带惩戒,出门忘了买装备,闪现送人头啊。痛定思痛,下定决心将这些基本操作好好整理一番日常背记,也当是做一个前端技能的分享和讨论了,希望广大前端爱好者能够在评论区查漏补缺。(结尾有惊喜哟)


1.基本类型和引用类型

基本类型:Number, String, Null, Undefined, Boolean, Symbol(ES6数据类型)

引用类型:Object、Array、RegExp、Date、Function、单体内置对象(Global、Math)

区别:基本类型,操作和保存在变量的实际的值(保存在栈区);引用类型,值指向内存空间的引用,就是地址,所指向的内存中保存着变量所表示的一个值或一组值,所以操作的是对象的引用(引用存放在栈区,实际对象保存在堆区)。

1.1 类型检测

使用 typeof进行基本类型检测,使用instanceof检测对象还是数组

类型 结果
Undefined "undefined"
Null "object"
Boolean "boolean"
Number "number"
String "string"
Symbol(ECMAScript 6 新增) "symbol"
函数对象 "function"
任何其他对象 "object"
检测数组和对象:(Array其实是Object 的子类)
var a = [];
console.log(a instanceof Array); // true
console.log(a instanceof Object); // true

var a = {};
console.log(a instanceof Array); // false
console.log(a instanceof Object); // true

1.2 String操作

String <=> Number:

字符串转数字:
parseInt(str, 进制) // 默认十进制, 转化为整数,小数点后默认不保留
parseFloat(str) // 转化为浮点数
+str // 屌屌的转化方法, 但字符串包含非数字会报错

数字转字符串:
let str1 = num.toString();
let str2 = String(num);
let str3 = num +  '';

String <=> Array:

字符串转数组
let arr = str.split(',') // 一般是空格或者逗号

数组转字符串
let str = arr.join('');

模板字符串

`Hello, ${变量}`

1.3 常用正则

去逗号
let newStr = str.replace(/,/g,'');
去空格(一般输入框输入都要做这个)
let newStr = str.replace(/(^\s*)|(\s*$)/g, ''); // 去除左右空格
let newStr = str.replace(/\s+/g,"");  // 去除所有空格
用户名
let userPattern = /^[a-zA-Z0-9_-]{4,16}$/; // 4到16位(字母,数字,下划线,减号)
userPattern.test(str);
电话号码
let mPattern = /^1[34578]\d{9}$/;
附:密码/身份证号/E-mail/URL就不上了,太长了背了没意义,用的时候查就好了

1.4 Array操作

在阿里腾讯头条的笔试机试中,对数组的操作可以说是前端算法的核心,数组操作的基本方法全是必背的重中之重。

1.4.1 Array.from()
  1. 伪数组对象和可迭代对象[见附录]转化为数组:

     let arr = Array.from(str/new Set()/new map());
    
  2. 转化数组后对每项进行操作

     let arr = Array.from('123', item => parseInt(item) + 1); // 2, 3, 4
    
  3. 去重(可以说这是最精彩的地方了)

     Array.from(new Set(arr));
    
1.4.2 拷贝数组

使用以下方法能复制数组保存在堆内存中的值,但不能深拷贝数组(数组中的数组或者对象依旧只是复制了引用没有复制到其在堆内存中的值)。[数组和对象的深浅拷贝以及for循环递归实现方式本文不涉及]

let arr2 = [...arr1];
let arr2 = arr1.slice();
let arr2 = arr1.concat([]); // 此方法不常用

深拷贝(对象也是如此)

let arr2 = JSON.parse(JSON.stringify(arr1));
1.4.3 找出最大最小值
Math.max.apply(null, arr);
Math.min.apply(null, arr);
// ES6的写法
Math.max(...arr);
1.4.4 数组排序
  1. sort()

     1.数组排序
     function compare(a, b) { return a-b; }
     arr.sort(compare);
     2.数组对象排序(开发中常用)
     function compare(property) {
         return (obj1, obj2) => {
             return obj1[property] - obj2[property];
         }
     }
     let students = [{name: "xx", age: 20}, {name: "hh", age: 19}];
     students.sort(compare('age'));
    
  2. 快排

1.4.5 其他方法
push(item) // 末尾添加
pop() // 删除末尾
shift() // 删除开头
unshift() // 开头添加
sort() // 排序
reverse() // 反转
slice(start, end) // 截断拷贝, 接收起始和结束位置两参数并返回相应的数组,不影响原数组
splice(index, num) // 切片,取出从index位置开始的num个值,原数组被截取
splice(index, 0, sth) // 插入sth
splice(index, 1, sth) // 替换为sth
▲  forEach(item, index, array) // 对每一项执行某些操作
▲  filter(item, index, array) // 返回满足条件(true)的项组成的数组
▲  map(item, index, array) // 返回对每一项执行某些操作组成的数组
every(item, index, array) // 如果该函数对每一项都返回true,则返回true
some(item, index, array) // 如果该函数对某一项返回true,则返回true
reduce() // 从头到尾逐个遍历,迭代数组中的所有项
includes(sth, index); // 检测数组中是否含有sth,index代表开始查找的位置,返回布尔值

另:二分查找

1.4.5 对象数组根据对象某key值去重(日常工作常用)
let arr = [{showId: 'C', age: '11'}, {showId: 'A', age: '11' },
{ showId: 'B', age: '11'}, { showId: 'B', age: '11'},
{ showId: 'B', age: '12'},{ showId: 'B', age: '13'}];

// 根据showId去重到新数组newArr
const newArr = [];
arr.forEach(item => {
  // 过滤,如果有重复项就添加到过滤数组,那么长度就不为0就不会推入新数组。
  // 如果没有重复项长度就为0就推入新数组。
  newArr.filter(m => m.showId === item.showId).length === 0 && 
  newArr.push(item);
});

1.5 Object操作

1.5.1 创建

创建方式:工厂模式、构造函数模式、原型模式、动态原型模式、寄生构造函数模式、稳妥构造函数模式。

工厂模式
function createObj(key) {
    const obj = new Object();
    obj.key = key;
    obj.sayKey = function(){ 方法 };
    return obj;
}
// 使用:const xuqingfeng = createObj('xuqingfeng');

构造函数(对象属性最好用构造函数) + 原型(对象方法最好用原型),这样的话每个实例都会有自己的一份实例属性的副本,同时又共享着对方法的引用,最大限度地节省了内存:

// 构造函数模式用于定义实例属性
function Person(name) {
    this.name = name;
}
// 原型模式用于定义方法和共享的属性
Person.prototype = {
    /* 默认情况下,所有原型对象都会自动获得一个constructor属性,
    这个属性是一个指向prototype属性所在函数的指针,
    这里的Person.prototype.constructor指向Person */
    constructor : Person, 
    sayName : function() { 方法 }
}
ES6的简写(简直不要太好用, 三大框架很多写法基于此):
属性简写:
let keyVal = 'xuqingfeng';
const obj = {keyVal}; // obj: { keyVal: 'xuqingfeng' }
方法简写:
const obj = {
    method() {}
};
获取对象属性:
 const { keyVal } = obj; // React的const { data } = this.props; 就是这么个原理,前提是对象中也有对应属性(key)
1.5.2 继承

继承方式:原型链、借用构造函数、组合继承、原型式继承、寄生式继承、寄生组合式继承。

组合继承

这种方式既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性。

function A_Obj(name) {
    this.name = name;
}
A_Obj.prototype.sayName = function() { A_Obj的方法 };
function B_Obj(name, age) {
    A_Obj.call(this, name); // 继承属性
    this.age = age;
}
B_Obj.prototype = new A_Obj(); // 继承A_Obj的所有方法
B_Obj.prototype.constructor = B_Obj; // 改变指向非常关键
B_Obj.prototype.sayAge = function() { B_Obj的方法 };

object.create()实现对象继承 - 特别地提及下这个方法,它可以直接使用创建一个新对象

// 实现继承 - 方法
let extend = (Child, Parent) => {
    Child.prototype = Object.create(Parent.prototype); // 拷贝Parent原型对象
    Child.prototype.constructor = Child; // 将Child构造函数赋值给Child的原型对象
}
// 实例
const Par = function () { this.name = 'xuqingfeng'; }
Par.prototype.getName = function () { return this.name; }
// 继承
const Cld = function () { Par.call(this); }
extend(Cld, Par);
// 使用
let testChild = new Cld();
console.log(testChild.getName())
1.5.3 拷贝

浅拷贝:

const copyObj = Object.assign({}, obj);
const Obj2 = {...Obj1};

浅拷贝并修改key的value或添加key与value: const Obj2 = {...Obj1, ['key']: 'newOrCover'},示例如下

const firObj = { a: '1', s: { ss: 'sss' } };
const secObj = { ...firObj, ['b']: '2' }
secObj.a = '777';
firObj.a = '666';
secObj.s.ss = 'secObj-s';
firObj.s.ss = 'firObj-s';
console.log(firObj, secObj);  // { a: '666', s: { ss: 'firObj-s' } } { a: '777', s: { ss: 'firObj-s' }, b: '2' }

并集-合并两个对象/数组,后者覆盖前者(深度覆盖),最终形成并集: const Obj3 = Object.assign({}, Obj1, Obj2);,示例如下

const firObj = { a: '1', b: 'b', s: { ss: 'fir-s' } };
const secObj = { a: '2', c: 'c', s: { ss: 'sec-s' } }
const newObj = Object.assign({}, firObj, secObj);
console.log(newObj); // { a: '2', b: 'b', s: { ss: 'sec-s' }, c: 'c' }
const firArr = [1, 2, 3, 'a', 'b'];
const secArr = [1, 3, 5, 7];
const newArr = Object.assign([], firArr, secArr);
console.log(newArr); // [ 1, 3, 5, 7, 'b' ]

深拷贝[ for循环递归深拷贝见上面数组,Object.assign合并对象和深拷贝移步MDN ]:

let obj2 = JSON.parse(JSON.stringify(obj1)); 
1.5.4 其他方法
Object.freeze() // 冻结对象:其他代码不能删除或更改任何属性。
Object.keys() // 返回一个包含所有给定对象自身可枚举属性名称的数组。
Object.values() // 返回给定对象自身可枚举值的数组。
Object.entries() // 返回给定对象自身可枚举属性的[key, value]数组
Object.defineProperty() // vue数据双向绑定的核心方法,建议上 MDN 一观

1.6 Function操作

1.6.1 参数转化为数组(不知参数个数)

数组原型slice方法

function fc() {
    Array.prototype.slice.call(arguments) ; // 这个方法可以将只要具有length属性的对象转成数组
}

▲ rest 参数

function fc(...arr) { console.log(arr); }

参数cancat为数组

function fc() { return [].concat.apply([], arguments); }
1.6.2 检测函数参数是否含有某个值(sth)
[].includes.call(arguments, sth)
1.6.3 函数设置可改的默认参数
function func1(a, b='123123',c={id: 1}){
    console.log(a,b,c)
}
func1('徐清风','xuqingfeng', 44) // 徐清风, xuqingfeng, 44

1.7 MathDate

Math方法:

Math.ceil() // 执行向上舍入
Math.floor() // 执行向下舍入
Math.round() // 执行标准舍入
▲ Math.random() // 返回大于等于0小于1的随机数

获取当前时间:

let now = new Date();
console.log(now.toLocaleString()); // 2018-8-23 17:48:47
console.log([now.getFullYear(), now.getMonth()+1, now.getDate()].join('-')); // 2018-8-23

2.JS编程基本操作

2.1 三元运算 - 用起来超刺激

公式:条件1 ? 真结果1 : ( 条件1.1 ? 真结果1.1 : (条件1.1.1 ? 真结果1.1.1:假结果1.1.1)), 一个常用示例:

node.style.display = (node.style.display === "block" ? "none" :  "block");

2.2 在做JS判断时的 truefalse (if判断、与非判断、三元运算判断等)

值为falsefalsenullundefined''(空字符串,空格不代表空)0NaN
值为truetrue对象字符串(包括空格)任意非0数值(包括Infinity)

2.3 与或非运算

&& :如果第一个值为 true,则 && 后面的值将显示在输出中,否则值为第一个值。

let a = false && 123; // false
let b = ' ' && 123; // 123, 注意这里是空格不是空

|| :如果第一个值为 false,则 || 后面的值将显示在输出中,否则值为第一个值。

let a = false || 123; // 123
let b = ' ' || 123; // ' '

附录:

  1. 伪数组对象和可迭代对象:
  • 伪数组对象(拥有一个 length 属性和若干索引属性的任意对象)
  • 可迭代对象(可以获取对象中的元素,如 MapSet 等)
  1. 福利-今年春秋招阿里腾讯头条机试(远程视频直接撸代码)题:

     1. 正则电话号码
     2. 两个超过JS数值范围的数字相加
     3. 一片英文文章重复出现次数最多的单词及其出现次数
     4. 创建一个 Person 类,其包含公有属性 name 和私有属性 age 以及公有方法 setAge;
        创建一个 Teacher 类,使其继承 Person ,并包含私有属性 studentCount 和私有方法 setStudentCount
     5. 兼容的事件监听方法
     6. 快排
     7. 拖拽一个方块随机移动
     8. 事件观察者
     9. promise按序执行三个函数
     10. 封装一个flat方法,将多维数组扁平化为一维数组
     11. 实现一个简易的JQ选择器功能(要求能够获取标签、类、Id)
     12. 实现简易的虚拟DOM(意味着用对象构造DOM),然后生成DOM结构,
         只要求属性值(比如class、id等属性能够正常获取和调用),
         不要求节点增删查改(这涉及到diff算法)。
     13. 对象数组根据某个属性去重【这个上面有提到】
    

以上知识点是个人日常开发常用的,关于编程思想、算法逻辑这些大知识点这里就不一一列出了,毕竟吃透这些东西不是光靠背下来就能解决的,更多的是积累、理解和自己的思考,这些东西是程序员一辈子都学不完的,所以列出毫无意义。
因为写这些小知识点也只是一时兴起,肯定有很多遗漏,文首就有提及过写这些内容的目的就是分享和讨论,所以欢迎大家在评论区进行补充,如果有必要的话可以在github上开一个issue。


2018-11-21 更新:新增数组、对象浅拷贝方法,新增获取对象key方法,新增对象数组去重方法,面试新题


2019-2-27 更新:新增常用的对象拷贝方法和合并方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,681评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,710评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,623评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,202评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,232评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,368评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,795评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,461评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,647评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,476评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,525评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,226评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,785评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,857评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,090评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,647评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,215评论 2 341