一、
JS数据中一共有8种:
ES5中有6种:String、Number、Boolean、空(Null)、未定义(Undefined)、Object
ES6新增了Symbol:这种类型的对象永不相等,即始创建的时候传入相同的值,可以解决属性名冲突的问题,做为标记
es10新增了bigInt:是指安全存储、操作大整数
JavaScript判断数据类型的方式有以下:
1、typeof
2、toString
Object.prototype.toString.call()
3、instanceof
表达为A instanceof B,是用来判断 A 是否为 B 的实例,返回一个布尔值
4、 constructor
JS规定每个构造函数都有一个prototype属性 ,即为构造函数的原型对象,而原型对象上会有一个constructor属性指回到构造函数,当利用构造函数创建对象时,原型上的constructor属性也会被继承到该新创建的对象上,从原型链的角度看,构造函数也代表了对象的类型
二、let、var、const的区别
(1)let和const具有块级作用域,var不存在块级作用域。
(2)变量提升: var存在变量提升,let和const不存在变量提升,即在变量只能在声明之后使用,否在会报错。
(3)var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会。
(4)重复声明: var声明变量时,可以重复声明变量,后声明的同名变量会覆盖之前声明的遍历。const和let不允许重复声明变量。
(5)在使用let、const命令声明变量之前,该变量都是不可用的。使用var声明的变量不存在暂时性死区。
(6)在变量声明时,var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。
(7)let创建的变量是可以更改指针指向(可以重新赋值)。但const声明的变量是不允许改变指针的指向。
三、call,apply,bind的区别与用法
call
、apply
与bind
都用于改变this
绑定
call、apply 在改变 this 指向的同时还会执行函数,一次性的。不同的是 call方法传递函数调用形参是以散列形式,而 apply 方法的形参是一个数组。在传参的情况下,call的性能要高于 apply,因为 apply 在执行时还要多一步解析数组。
bind 在改变 this 后是返回一个全新的绑定函数,即返回一个新的函数,不直接执行函数。并且此后 this 的指向无法在通过 call、apply、bind 改变。
四、对象创建的方式
1、工厂模式
function createPerson(name, age, job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.name);
};
return o;
}
var person1 = createPerson("Nicholas", 29, "Software Engineer");
2、构造函数模式
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
};
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
// 当作构造函数使用
var person = new Person("Nicholas", 29, "Software Engineer");
person.sayName(); //"Nicholas"
// 作为普通函数调用
Person("Greg", 27, "Doctor"); // 添加到 window
window.sayName(); //"Greg"
3、原型模式
function Person(){}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName();
//"Nicholas"
var person2 = new Person();
person2.sayName();
//"Nicholas"
alert(person1.sayName == person2.sayName);
//true
五、浏览器的垃圾回收机制
Javascript代码运行时,需要分配内存空间来存储变量和值。当变量不在参与运行时,就需要系统收回被占用的内存空间,这就是垃圾回收。
浏览器通常使用的垃圾回收方法有两种:标记清除,引用计数
六、New操作符的执行过程
当使用new
关键字调用一个函数时,会发生以下几个步骤:
- 创建一个空对象。这个对象会继承自函数的原型(
prototype
)属性。 - 将创建的空对象作为函数的上下文(
this
)。 - 执行函数体内的代码。在执行过程中,如果函数内部有对
this
的引用,那么它将指向这个新创建的对象。 - 如果函数没有返回其他对象,那么
new
表达式将返回这个新创建的对象。否则,返回的是函数返回的对象。
下面是一个简单的例子,说明new
操作符的执行过程:
function Person(name) {
this.name = name;
}
// 使用new关键字调用Person函数
var john = new Person('John');
console.log(john.name); // 输出: "John"
在上述例子中,调用new Person('John')
时,首先会创建一个空对象。然后,将这个空对象作为函数Person
的上下文。接着,执行函数体内的代码,将name
属性赋值为'John'
。最后,返回这个新创建的对象,并将其赋值给变量john
。
需要注意的是,new
关键字只适用于构造函数(通过函数来创建对象的一种特殊形式),而不适用于其他类型的函数。
七、数组扁平化去并除其中重复部分数据
function flattenAndRemoveDuplicates(arr) {
// 用于存储扁平化后的元素
var flattenedArr = [];
// 递归函数,用于处理多维数组
function flatten(arr) {
arr.forEach(function(element) {
if (Array.isArray(element)) {
flatten(element); // 递归处理嵌套的数组
} else {
flattenedArr.push(element); // 将非数组元素添加到结果数组中
}
});
}
flatten(arr);
// 使用 Set 对象去除重复元素,然后转换为数组
var uniqueArr = Array.from(new Set(flattenedArr));
// 对数组进行升序排序
var sortedArr = uniqueArr.sort(function(a, b) {
return a - b;
});
return sortedArr;
}
var arr = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10];
var result = flattenAndRemoveDuplicates(arr);
console.log(result);
八、代码输出题
1.箭头函数梳理
1.1 什么是箭头函数
ES6中允许使用=>来定义函数。箭头函数相当于匿名函数,并简化了函数定义。箭头函数就是采用箭头=>来定义函数,省去关键字function。函数的参数放在=>前面的括号中,函数体跟在=>后的花括号中。
// 箭头函数
let fn = (name) => {
// 函数体
return `Hello ${name} !`;
};
// 等同于
let fn = function (name) {
// 函数体
return `Hello ${name} !`;
};
箭头函数没有原型prototype,因此箭头函数没有this指向
2.JS宏任务和微任务
(1)宏任务
分类:setTimeout setInterval requrestAnimationFrame
1>这些都是浏览器或者Node环境实现的。
2>第一个宏任务列中只有一个任务,执行主线程的js代码
3>宏任务队列可以有多个
(2)微任务
分类:new promise().then(回调) process.nextTick
1.微任务所处的队列 就是微任务队列
2.只有一个微任务队列
3.在上一个宏任务队列执行完毕后如果有微任务队列就会执行微任务队列中所有的任务,如果在执行微任务的过程中,产生了新的微任务,同样会将该微任务添加到微任务队列中,V8 引擎一直循环执行微任务队列中的任务,直到队列为空才算执行结束。也就是说在执行微任务过程中产生的新的微任务并不会推迟到下个宏任务中执行,而是在当前的宏任务中继续执行。
3.作用域及this指向
this指向的是一个对象,我们把this指向的对象叫做函数执行的上下文对象,当函数被调用的时候,this指向会发生改变,指向调用函数的对象,this跟函数的调用有关,看最后一步函数怎么调用**,方法调用哪个对象,this就指向谁**
this绑定的规则
优先级: 默认(函数名()调用)< 隐式(对象.方法()调用) < 显示(call和apply方法) < new 操作符