文章目录
内存溢出和内存泄漏
1、内存溢出
//内存溢出
var obj = {};
for(var i =0;i<10000;i++){
obj[i] = new Array(1000000);
console.log('--------');
}
2、内存泄漏
- 占用的内存没有及时释放
- 常见的内存泄漏
(1)意外的全局变量
(2)没有及时清理的计时器或回调函数
(3)闭包
//内存泄漏
//(1)意外的全局变量
function fn(){
a = 3;//没用var直接赋值,是全局变量
console.log(a);
};
//(2)启动循环计时器后不清理或者没有及时清理的回调函数
var intervalId = setIntterval(function(){
console.log('---');},1000
)
//需要清理
clearInterval(intervalId);
//(3)闭包的内存泄漏
function fn1(){
var a = 4;
function fn2(){
console.log(++a);
};
return fn2;
};
var f = fn1();
f();
//使用f = null可以清理
闭包面试题
一、面试题1
1、测试题一
var name = 'The window';
var object = {
name:'My object',
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()());//输出The window
2、测试题二
var name2 = 'The window';
var object2 = {
name2:'My object',
getNameFunc : function(){
var that = this;//在这里定义的this已经指向了object
return function(){
return that.name2;
};
}
};
alert(object2.getNameFunc()());//输出my object
对象创建模式
1、方式一:Object构造函数模式
套路:先创建空Object对象,再动态添加属性/方法
适用场景:起始时不确定对象内部数据
问题:语句太多
var p =new Object();
p.name = 'Tom';
p.age = 12;
p.setName = function(name){
this.name = name;
}
2、方式二:对象字面量模式
套路:使用{ } 创建对象,同时指定属性/方法
适用场景:起始时对象内部数据是确定的
问题:如果创建多个对象,有重复代码
var p ={
name :'Tom',
age : 12,
setName : function(name){
this.name = name;
}
};
3、方式三:工厂模式
套路:使用工厂函数(返回一个对象的函数称为工厂函数)动态创建对象并返回
适用场景:需要创建多个对象
问题:对象没有一个具体的类型,都是Object类型
function creatPerson(name,age){
var obj = {
name:name,
age:age,
setName:function(name){
this.name = name;
}
};
return obj;
}
var p1 = creatPerson('TOM',13);
var p2 = creatPerson('bob',15);
function creatStudent(name,price){
var obj = {
name:name,
price:price,
};
return obj;
}
var s1 = creatPerson('张三',13000);
//s1与p1,p2都是对象类型,区别不开
4、方式四:自定义构造函数模式
套路:自定义构造函数,通过new创建对象
适用场景:需要创建多个类型确定的对象
问题:每个对象都有相同的数据,浪费内存
function Person(name,age){
this.name = name;
this.age = age;
this.setName = function(name){
this.name = name;
}
}
var p1 = new Person('TOM',12);
P1.setName('JACK');
console.log(p1.name,p1.age);
console.log(p1 instanceof Person);
var p2 = new Person('ff',23);
console.log(p1,p2);//p2与p1中有相同的数据,浪费内存
function Student(name,price){
this.name = name;
this.price = price;
}
var s = new Student('bob',12000);
console.log(s instanceof Student);
5、方式五:构造函数+原型的组合模式
套路:自定义构造函数,属性在函数中初始化,方法添加到原型上
适用场景:需要创建多个类型确定的对象
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.setName = function (name){
this.name = name;
}
var p1 = new Person('TOM',12);
var p2 = new Person('ff',23);
console.log(p1,p2);//方法在原型上面
2.继承模式
2.1原型链继承
方式1:原型链继承
套路 1.定义父类型构造函数
2.给父类型的原型添加方法
3.定义子类型的构造函数
4.创建父类型的对象赋值给子类型的原型
5.将子类型原型的构造属性设置为子类型
6.给子类型原型添加方法
7.创建子类型的对象:可以调用父类型的方法
关键
1.子类型的原型为父类型的一个实例对象
//父类型
function Supper() {
this. supProp = 'Supper property'
Supper. prototype. showSupperProp = function() {
console.log(this . supProp)
}
//子类型
function Sub() {
this.subProp = ' Sub property'
//子类型的原型为父类型的-一个实例对象
Sub. prototype = new Supper()
//让子类型的原型的constructor指向子类型
Sub. prototype . constructor = Sub
Sub. prototype . showSubProp = function () {
console.log(this . subProp)
var sub = new Sub()
sub. showSupperProp()
// sub. toString()
sub. showSubProp()
2.2借用构造函数继承
方式2:借用构造函数继承(假的)
1.套路:
1.定义父类型构造函数
2.定义子类型构造函数
3.在子类型构造函数中调用父类型构造
2.关键:
1.在子类型构造函数中通用super()调用父类型构造函数
function Person(name, age) {
this. name = name
this.age = age
}
function Student(name, age, price) {
Person. call(this, name, age) // 相当于: this. Person(name, age )
/*this. name = name
this.age = age*/
this.price = price
}
var s =new
Student( 'Tom', 20, 14000 )
console.1og(s.name, s.age, s.price)
2.3组合继承
方式3:原型链+借用构造函数的组合继承
1.利用原型链实现对父类型对象的方法继承
2.利用super()借用父类型构建函数初始化相同属性
function Person(name, age) {
this.name = name
this.age = age
}
Person. prototype . setName = function (name) {
this. name = name
}
function Student(name, age, price) {
Person.call(this, name, age) // 为了得到属性
this.price = price
}
Student. prototype = new Person() //为了能看到父类型的方法
Student . prototype. constructor = Student // 修正constructor属性
Student . prototype.setPrice = function (price) {
this.price = price
}
var s = new Student('Tom', 24,15000)
s. setName('Bob')
s. setPrice(16000)
console.1og(s.name, s.age, s.price)
进程和线程
1、进程
程序的一次执行,它占有一片独有的内存空间
可以通过windows任务管理器查看进程
2、线程
- 是进程内一个独立执行单元
- 是程序执行的一个完整流程
- 是CPU的最小的调度单元相关知识
相关知识
何为多线程与多进程?
(1)多进程运行:一应用程序可以同时启动多个实例运行
(2)多线程:在一个进程内,同时有多个线程运行
比较单线程和多线程?
(1)多线程:
优点:能有效提升CPU的利用率
缺点:创建多线程开销;线程之间切换开销;死锁与同步问题
(2)单线程:
优点:顺序编程简单易懂
缺点:效率低
JS是单线程还是多线程?
(1)js是单线程运行的
(2)但使用H5中的Web Workers 可以多线程运行
浏览器运行是单线程还是多线程?
(1)都是多线程运行的
浏览器运行是单进程还是多进程?
(1)有的是单进程:firefox; 老版IE
(2)有的是多进程:chrome;新版IE
事件循环模型
1、所有代码分类
初始化执行代码(同步代码):包含绑定dom事件,设置定时器,发送ajax请求的代码
回调执行代码(异步代码):处理回调逻辑
2、js引擎执行代码的基本流程:
初始化代码===>回调代码
3、模型的2个重要组成部分:
事件管理模块
回调对列
4、模型的运转流程
执行初始化代码,将事件回调函数交给对应的模块管理
当事件发生时,管理模块会将回调函数及其数据添加到回调队列中
只有当初始化代码执行完后(可能要一定的时间),才会遍历读取回调队列里的回调函数执行