(一)Javascript
1. 原始值和引用值类型及区别
数据类型 | 释义 |
---|---|
原始值 | 原始值是存储在栈(stack)中的简单数据段 (Undefined,Null,Boolean,Number、String) |
引用值 | 引用值是存储在堆中的对象,这个时候变量中存放的是对象的指针,指向对象的内存空间。(Array, Oject, function…Date ,RegExp) |
举例
var x = 1; //1就是一个原始值,变量x中存放的就是原始值本身1
var o = {}; //{}这个对象是一个引用值,注意变量o中并没有存放这个对象,而是存放的这个对象的指针
区别
原始类型:不论是变量名还是原始值都在栈中。
当把一个原始变量传递给另一个原始变量时,是把一个栈房间的东西复制到另一个栈房间,且这两个原始变量互不影响。
引用类型:变量名在栈中,数值在堆中,他们中间通过指针进行连接。 当把引用对象传递给另一个变量时,复制的其实是指向实际对象的指针, 此时
两者指向的 是同一个数据,若通过方法改变其中一个变量的值,则访问另一个变量时,其值也会随之加以改变;但若不是通过方法 而是通过 重新赋值
此时 相当于 重新开了一个房间 该值的原指针改变 ,则另外一个 值 不会随他的改变而改变。
2. 判断数据类型typeof、instanceof、Object.prototype.toString.call()、constructor
参考原文链接: https://blog.csdn.net/zjy_android_blog/article/details/81023177.
在写封装的插件或者函数时,常常用到JS的数据类型判断,典型的案例就是深度拷贝函数用到数据类型判断
typeof
console.log(typeof 2); // number
console.log(typeof true); // boolean
console.log(typeof 'str'); // string
console.log(typeof []); // object []数组的数据类型在 typeof 中被解释为 object
console.log(typeof function(){}); // function
console.log(typeof {}); // object
console.log(typeof undefined); // undefined
console.log(typeof null); // object null 的数据类型被 typeof 解释为 object
能够判断出大多数的数据类型,但是对空数组和null的数据类型判断不够精确。而后的instanceof数据类型判断方法解决了这一问题
instanceof
console.log(2 instanceof Number); // false
console.log(true instanceof Boolean); // false
console.log('str' instanceof String); // false
console.log([] instanceof Array); // true
console.log(function(){} instanceof Function); // true
console.log({} instanceof Object); // true
// console.log(undefined instanceof Undefined);
// console.log(null instanceof Null);
————————————————
可以看出instanceof的类型判断方法是判断对象是否为数字类型实例,只有引用数据类型(Array,Function,Object)被精准判断,其他(数值Number,布尔值Boolean,字符串String)字面值不能被instanceof精准判断.
对于null和undefined浏览器无法判断,实际他们就是对应null型和undefined型。
constructor
constructor几乎可以完美地将这6种类型进行判断,但是遇到特殊情况,例如:
function Fn(){};
Fn.prototype=new Array();
var f=new Fn();
console.log(f.constructor===Fn); // false
console.log(f.constructor===Array); // true
已经改变过类型的对象,不能准确判断出其原对象。可以解决这个问题的是下面这个大招
Object.prototype.toString.call()
var a = Object.prototype.toString;
console.log(a.call(2));
console.log(a.call(true));
console.log(a.call('str'));
console.log(a.call([]));
console.log(a.call(function(){}));
console.log(a.call({}));
console.log(a.call(undefined));
console.log(a.call(null));
使用 Object 对象的原型方法 toString ,使用 call 进行狸猫换太子,借用Object的 toString 方法
即使原型改变了也可以正确判断。
3.类数组与数组的区别与转换
类数组的定义
1)拥有length属性,其它属性(索引)为非负整数(对象中的索引会被当做字符串来处理);
2)不具有数组所具有的方法;
javascript中常见的类数组有 arguments对象和 DOM方法的返回结果。比如 document.getElementsByTagName()。
//例如:定义一个类数组
let person = {
0:"小蜜",
1:"18",
length:2
}
console.log(person.length)
区别:
类数组对象不能调用数组原型上的方法。就是:xx.push()、xx.slice()、xx.indexOf() 等等这些方法都不能用。
转换方法:将类数组转为对象
Array.prototype.slice.call(person);
或者
Array.from(person);
4. 数组的常见API
参考来源
https://blog.csdn.net/weixin_33754913/article/details/88695141
unshift push shift pop
- 会对原数组造成改变
- unshift()从前添加元素,push()从尾添加元素,返回数组长度
- shift()删除第0个元素,pop()删除最后一个元素,返回被删除的元素
slice
- 不会对原来的数组造成改变
- slice(m, n)返回原数组索引m(包含)到n(不包含)的元素数组。不传参数默认全部截取,只传一个参数,从该位置截取到末位。类似于String.prototype.substring
let arr = [1,2,3,4,5]
console.log(arr.slice()); // [ 1, 2, 3, 4, 5 ]
console.log(arr.slice(1)); // [ 2, 3, 4, 5 ]
console.log(arr.slice(2,4)); // [ 3, 4 ]
console.log(arr); // [1,2,3,4,5]
splice
- splice(index,howmany,item1,item2…)index表示从第几个位置开始添加元素,howmany代表删除多少元素,如果是0则不删只添,item开始是要填入的元素。若只写index,则从index位置开始删除到末位。
let arr = [1,2,3,4,5];
console.log(arr.splice(2), arr); // [ 3, 4, 5 ] [ 1, 2 ]
console.log(arr.splice(0,1,2), arr); // [ 1 ] [ 2, 2, 3, 4, 5 ]
concat
- 拼接不改变原数组
let arr = [1,2,3], arr1 = [4];
console.log(arr.concat(arr1, 5), arr); // [ 1, 2, 3, 4, 5, ] [ 1, 2, 3 ]
console.log([...arr, ...arr1, 5]); // [ 1, 2, 3, 4, 5 ] (对象也可以这样拼接,但重复的会覆盖,相当与 Object.assign)
of 和 from
- of()类似于new Array(),但后者如果传入一个参数,则是设置数组长度。 from()
- 把伪数组转换为真数组,类似于[].slice.call()(或者写成Array.prototype.slice.call())
- 伪数组有DOM集、arguments、{0: ‘zero’, 1: ‘one’, length: 2}
判断数组的方法有
- xx instanceof Array
- Array.isArray()
- Object.prototype.toString.call() === ‘[object Array]’
indexOf 和 includes
- indexOf() 返回索引,不存在就返回 -1。inclues()返回布尔值。
- NaN 不能通过indexOf()判断,它是通过“===”比较的。
arr = [1, '2', null, NaN];
arr.indexOf(NaN); // -1
arr.includes(NaN); // true
filter、find 和 findIndex
- filter() 返回数组。find() 返回值,不存在就返回 undefined。 findIndex() 返回第一个匹配到的索引,不存在就返回 -1。
let arr = [1, '2', null, NaN];
arr.filter(item => typeof item === 'number'); // [1, NaN]
arr.find(item => typeof item === 'number'); // 1
arr.findIndex(item => typeof item === 'number'); // 0
5.bind、call、apply的区别
参考链接:https://www.jb51.net/article/99797.htm
- 三种方法都是用于改变this的指向
- call()和apply()唯一区别是参数不一样,call可以接收一个参数列表,而apply只接受参数数组
- bind()是返回一个新函数,供以后调用,而apply()和call()是立即调用。
#三者实现示例:
function keith(a, b) {
return a + b;
}
console.log(keith.apply(null,[1,4])); //5
console.log(keith.call(null,1,4)); //5
console.log(keith.bind(null, 1, 4)); //keith()
console.log(keith.bind(null, 1, 4)()); //5
6. new的原理
- 如何正确判断this?
- 闭包及其作用
- 原型和原型链
10.prototype与__proto__的关系与区别