一、变量、JS部分
一.JS的数据类型
- 基本数据类型 (number, string, boolean, null[空指针], undefined) 存储的是值
- 引用数据类型(object[[]], {},new Boolean()], function) 存储的是引用地址(指向同一个内存地址,一个变,另一个会随之改变)
- es6 symobl [Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象]
注意: 基本数据类型用new关键字也会变成一个一个应用数据类型,是一个实例了
如何判断一个值是否是null
function checkNull(val) {
return typeof val === 'object' && val === val;
}
checkNull()
复制代码
如何判断一个值是否是NaN
- Object.is(); es6
- toSring()返回'NaN'
function checkNaN(val) {
return val.toSring() === 'NaN';
}
checkNull()
复制代码
二.如何检测数据类型
-
typeof typeof() 是一个一元运算符,可以不加括号,是等价的, 返回一个类型字符串 用法==>> typeof typeof()
- 只能检测基本数据类型,不能区分引用数据类型,引用数据类型都返回'object'
- 如何区分null和object类型
- 如何区分function 和 symbol类型
有六种结果==>: 'number', 'string', 'boolean', 'object'[null], 'function'[Symobl], 'undefined' typeof null = > 'object' typeof Symobl('es6') => 'function' typeof typeof typeof typeof [] => 'string' 复制代码
-
instanceof 只要在原型链上即可, 用法==>> 值 instanceof 类
- Object类是所有类的基类
- Function类是所有函数的基类
[] instanceof Array // true
[] instanceof Object // true
null instanceof Object //false null空对象使用
复制代码
- constructor 利用函数原型上的constructor执行类本身去判断(原型链机制去查找)
- 在原型继承的时候会打断了,需要手动设置construct的值 [子类的.prototyep.constrcutor = 子类]
机制是:实例.__proto ===类的.prototype.constructr
function fn() {}
[].constrcutor === Array; / false
fn.constrcutor === Object // false
fn.constructor === Function //true
function A() {}
A.prototype.getX() {};
function B() {}
B.protype = new A();
B.prototype.constructor = B; //====>>手动设置constructor的值,设置会执行父类A
复制代码
- Object.prototype.toString.call(val) 返回'[object 类的本身]' 改变this,返回类本身,最好的
1.封装检测数据类型和判断数据类型各个方法
const tool = function(window, undefined) {
let box = {
checkTypeof(val) {
return Object.prototype.toString.call(val);
},
isNumber(val) {
return Object.prototype.toString.call(val) === '[object Number]';
},
isString(val) {
return Object.prototype.toString.call(val) === '[object String]';
},
isBoolean(val) {
return Object.prototype.toString.call(val) === '[object Boolean]';
},
isNull(val) {
return Object.prototype.toString.call(val) === '[object Null]';
},
isUndefined(val) {
return Object.prototype.toString.call(val) === '[object Undefined]';
},
isFunction(val) {
return Object.prototype.toString.call(val) === '[object Function]';
},
isObject(val) {
return Object.prototype.toString.call(val) === '[object Object]';
},
isArray(val) {
return Object.prototype.toString.call(val) === '[object Array]';
},
isSymbol(val) {
return Object.prototype.toString.call(val) === '[object Symbol]';
},
isExpRep(val) {
return Object.prototype.toString.call(val) === '[object ExpRep]';
},
};
return box;
}();
2. 如何判断一个变量是否是数组
- instanceof val instanceof Array
- constrcutor val.constrcutor === Array
- Array.isArray(val)
- Object.prototype.toString.call(val) ==> '[object Array]' => 最靠谱,最安全
注意:constrcutor和isArray在两个iframe,在哪个iframe中间判断,因为是俩个window对象,会有问题
复制代码
三、数组方法
- es3
push => pop
unshift => shift
splice(n, m, val) 截取 从n,删除m个元素,用val去替换
slice(n,[m]) 筛选,从索引n,查找到索引m,不包含m
conact 合并数组
reverse 倒叙 判断回文数面试题
sort((a,b) => a-b); 排序, 原理是冒泡排序 手写冒泡排序
indexOf([n]) => lastIndexOf([n]) 原理是,遍历进行===进行比较,所以NaN是找不到的 NaN === NaN =>false 查找这个东西,返回索引值,没有返回-1,前,后查找
join 手拉手 转为字符串 split劈开转为数组
复制代码
- es5 都是callback进行处理,不会改变原来数组, 自己封装
forEach 遍历
filter 过滤,筛选出符合条件的数据
map 映射, 一组数据对应
reduce 计算
some 全部是否符合
every 任意一个符合
myForEach:
Array.prototype.myForEach = function (callback) {
if (typeof callback == 'function') {
for (let i = 0; i < this.length; i++) {
callback.call(this, this[i], i, this);
}
}
};
myMap:
Array.prototype.myMap = function (callback) {
let ary = [];
if (typeof callback == 'function') {
for (let i = 0; i < this.length; i++) {
ary.push(callback.call(this, this[i], i, this));
}
}
return ary;
};
myFilter:
Array.prototype.myFilter = function (callback) {
let ary = [];
if (typeof callback == 'function') {
for (let i = 0; i < this.length; i++) {
if (callback.call(this, this[i], i, this)) {
ary.push(this[i]);
}
}
}
return ary;
};
复制代码
- es6
find => findIndex 数组实例的find方法,用于找出第一个符合条件的数组成员
fill(val) 快速填充数组,
includes =>原理Ojbect.is(),所以他可以处理数组里面的NaN值,查找某个元素在数组里面,找到返回true,反之false
复制代码
*** 1.哪些方法是改变原来的数组
push pop shift unshift splice sort reverse
其他返回原数组,或者布尔值,索引
复制代码
*** 2.手写冒泡排序
Array.prototype.mySort = function() {
for(let i=0;i<this.length-1;i++) {
for(let k=0;k=this.length-1-i;k++) {
if(this[k] > this[k+1]) {
let templ = this[k];
this[k] = this[k+1];
this[k+1] = this[k];
}
}
}
return this;
};
复制代码
*** 3.在数组里面查找NaN
- indexOf, lastIndexOf, 循环遍历,严格比较(===) 处理不了NaN
- includes =>Object.is()原理 处理NaN的
*** 4.如何快速创建10000个值都是为1的数组
let ary = new Array(1000).fill(1);
console.log(ary);
复制代码
四、数组去重
*** 由于考虑NaN问题,比较会返回false问题,我们一律采用Object.is()方法,查找一律采用includes方法
- 创建空数组,循环判断进行push, 注意,考虑到NaN最好用includes, 建议不用indexOf过滤不掉的,NaN ===NaN false
Array.prototype.myUnique = function () {
let ary = [];
for (let i = 0; i < this.length; i++) {
console.log(ary.includes(this[i]))
if (!ary.includes(this[i])) {
ary.push(this[i]);
}
}
return ary;
}
let s= ([1, 2, 2, 1, 3, 4, 1, 2, 3,NaN, null,NaN].myUnique())
复制代码
- 原数组进行排序,相邻进行对比,重复,splice删除,i--
Array.prototype.myUnique = function () {
this.sort((a, b) => a-b);
for(let i=0;i<this.length;i++) {
if (this[i] === this[i+1]) { ==>>Object.is(this[i], this[i+1])
this.splice(i ,1);
i--;
continue;
}
}
return this;
}
var s= [1, 2, 2, 1, 3, 4, 1, 2, 3,NaN, null,NaN].myUnique();
[null, 1, 2, 3, 4, NaN, NaN]; 去不掉NaN, 因为NaN === NaN;是不相等的,NaN除了数字其他东西,鬼知道呢
====>> 优化去掉NaN;
this[i] === this[i+1]不可以排除,我们用Object.is(this[i], this[i+1])不就可以了嘛
复制代码
- 对象去重复(对象的属性不能重复)
Array.prototype.myUnique = function () {
let obj = {};
for (let i = 0; i < this.length; i++) {
let cur = this[i];
if (obj[cur] === cur) { // ===>> Object.is(obj[cur] === cur)
this.splice(i, 1);
i--;
continue;
}
obj[cur] = cur;
}
obj = null; // ===>>释放内存,优化
return this; // ===>> 链式调用
}
var s = [1, 2, 2, 1, 3, 4, 1, 2, 3, NaN, null, NaN].myUnique();
s => [1, 2, 3, 4, NaN, null, NaN]
也是严格对NaN问题,Object.is(obj[cur] === cur)
复制代码
- es6 [ ...new Set(val) ] set数据解构配合数组拓展符运算符
Array.prototype.myUnique = function () {
return [... new Set(this)]
}
var s = [1, 2, 2, 1, 3, 4, 1, 2, 3, NaN, null, NaN].myUnique();
s ==> [1, 2, 3, 4, NaN, null]
复制代码
四、伪数组转为数组
1.伪数组:
- DOM选择器选择出来的列表
- 函数的arguments对象
- jQ里面的选择出来的对象是
2.转换为数组
第一种方法,封装方法,遍历push
function toArray(likeAry) {
if (likeAry && likeAry.length) {
let ary = [];
for (let i = 0; i < this.length; i++) {
ary.push(this[i]);
}
return ary;
}
return [];
}
console.log(toArray(document.getElementsByTagName('*')) instanceof Array) // true
复制代码
第二种方法,借助数组原型上的方法slice,截取,改变this执行,上面是slice的封装
- Array.prototype.slice.call(likeAry);
- [].slice(likeAry); ==> [].proto..slice
function fn() {
arguments = Array.prototype.slice(arguments);
arguments = Array.from(arguments);
}
复制代码
第三种方法,es6 Array.from(likeAry);
function toArray(likeAry) {
return Array.from(likeAry);
}
复制代码
五、遍历数组方法总结 (面试题)
=>说说for、 for-in、 forEach 、for -of 区别
- for循环
- 不会遍历出私有的属性
- 编程式,知道原理
- forEach循环
- 不能return
- 不能遍历出私有属性
- 声明式编程, 不知道原理,用即可, vue就是
- for - in 循环
- 可以遍历出私有的属性,利用hasOwnproperty()进行过滤
- for - of循环 ES6完美解决上面问你
- 可以return
- 不会遍历出私有的属性
- 只能遍历数组
- myForEach封装,就是回调函数(在原型上扩展)
Array.prototype.myForEach = function(callback) {
if (typeof callback == 'function') {
for (let i =0;i<this.length;i++) {
callback.call(this,this[i], i, this);
}
}
};
var ary = ['vue', 'react', 'angular'];
ary.myForEach(function(item, index, slef) {
console.log(item, index, slef)
});
复制代码
1.for循环 // ==>> 不会遍历出私有的属性
let ary = [1, 2, 3];
ary.b = 100;
for (let i=0,len=ary.length;i<len;i++) {
console.log(ary);
}
2. forEach // ==>> 不能return,不会遍历出私有的属性
ary.forEach((item, index, self)=> {
console.log(item);
});
3.for - in // ==>> key会变成字符串,并且会遍历出私有的属性,利用hasOwnproperty进行过滤
for(let key in ary) {
if (!ary.hasOwnproperty(key)) {
conosle.log(key)
}
}
4.for - of // ==>> 可以return, 但是必须是数组,不能遍历对象
for(let key of ary) {
}
实现想遍历对象: Object.keys(); //====>>将一个对象的属性依次放到一个数组中,返回一个新的数组
let obj = {school:'科师',age:9};
for (let key of Ojbect.keys(obj) {
console.log(obj[key]);
}
复制代码
四、字符串方法
- es3
chartAt(index) 返回子字符串,index为字符串下标,index取值范围[0,str.length-1]
chatCodeAt(index) 返回子字符串的unicode编码,index取值范围同上
查找方法:
indexOf(searchString,startIndex)返回子字符串第一次出现的位置,从startIndex开始查找,找不到时返回-1
lastIndexOf(searchString,startIndex) 从由往左找子字符串,找不到时返回-1
截取方法
substr(start,end) 两个参数都为正数,返回值:[start,end) 也就是说返回从start到end-1的字符
substring(start,end) 返回从 start 到 end(不包括)之间的字符,start、end均为 非负整数。若结束参数(end)省略,则表示从start位置一直截取到最后。
slice 两个参数可正可负,负值代表从右截取,返回值:[start,end)也就是说返回从start到end-1的字符
字符串分割成数组
str.split(separator,limit); 参数1指定字符串或正则,参照2指定数组的最大长度
- str.split(""); 每个字符都被分割 ['','','','']
- str.split(); 整个字符串放到数组里 ['']
str.replace(rgExp/substr,replaceText) 返回替换后的字符串
英文转换
toLowerCase() 转小写
toUpperCase() 转大写
复制代码
后续每天更新