前端学习知识体系(new,闭包,内存溢出和内存泄露)

一、new操作符

  • 首先对new操作符进行后的操作进行一个简单的了解。
    • 当使用new来创建对象时,该函数就是构造函数,JS将新对象的原型链指向了构造函数的原型对象,于是就在新对象和函数对象之间建立了一条原型链,通过新对象可以访问到函数对象原型prototype中的方法和属性。
      首先来看一段代码
function Animal(name){
    this.name = name;
}
 Animal.color = "black";
 Animal.prototype.say = function(){
    console.log("I'm " + this.name);
 };
 var cat = new Animal("cat");
 
 console.log(
     cat.name,  //cat
     cat.height //undefined
 );
 cat.say(); //I'm cat
 
 console.log(
     Animal.name, //Animal
     Animal.color //back
 );
 Animal.say(); //Animal.say is not a function

可以看到经过原型的学习可以知道,new出来的新对象可以访问父类的原型,但是父类不可以访问自己的原型。

  • 剖析 new 的内部原理
//这句代码的意思就是new一个cat出来,并且传参数cat
var cat = new Animal("cat");

Animal 本身是一个普通函数,但当通过new来创建对象时,Animal 就是构造函数。
JS引擎执行这句代码时,在内部做了很多工作,用伪代码模拟其内部流程如下:

1 new Animal('cat') = {
2    var obj = {};
3    obj.__proto__ = Animal.prototype;
4    var result = Animal.call(obj,"cat");
5    return typeof result === 'object'? result : obj;
}

【1】创建一个空对象 obj;

【2】把 obj 的__proto__ 指向构造函数 Animal 的原型对象 prototype,此时便建立了 obj 对象的原型链:obj->Animal.prototype->Object.prototype->null

【3】在 obj 对象的执行环境调用 Animal 函数并传递参数 “ cat ” 。 相当于 var result = obj.Animal(“cat”)。
当这句执行完之后,obj 便产生了属性 name 并赋值为 “cat”。

【4】考察第 3 步的返回值,如果无返回值 或者 返回一个非对象值,则将 obj 作为新对象返回;否则会将 result 作为新对象返回。

根据以上过程,
在回去看看

var cat = new Animal('cat')

我们发现 cat 对象其实就是【4】的返回值

cat 的原型链是:cat->Animal.prototype->Object.prototype->null
cat上新增了一个属性:name

然后
对 new 运算符有了较深入的理解之后,我们再回到开篇提到的问题:在JavaScript 中,万物皆对象,为什么还要通过 new 来产生对象?
其实
通过 new 创建的 对象 和 构造函数 之间建立了一条原型链,原型链的建立,让原本孤立的对象有了依赖关系和继承能力,让JavaScript 对象能以更合适的方式来映射真实世界里的对象,这是面向对象的本质。

function foo(){
	getName = function (){
		console.log(1998)
	}
	console.log(this)
	return this;
}
foo.getName = function(){
	console.log(2)
}
foo.prototype.getName = function(){
	console.log(3)
}
var getName = function(){
	console.log(4)
}
function getName(){
	console.log(5)
}
foo.getName(); //2
getName();  //4
foo().getName(); //win 1
getName();  //1 这里得到1是受前面的foo().getName()影响
new foo.getName();//2
new foo().getName(); //foo 3
new new foo().getName(); //foo 3

闭包

简单解释一下,闭包是一个具有独立作用域的静态执行环境。和函数作用域不同的是,闭包的作用域是静态的,可以永久保存局部资源,而函数作用域只存在于运行时,函数执行结束后立即销毁。因此,闭包可以形成一个独立的执行过程。
然后实际研究一下里面的内容
首先看代码

function A(){
    function B(){
       console.log('Hello Closure!');
    }
    return B;
}
var C = A();
C();// Hello Closure!

以上代码的意思是
函数A的内部函数B被函数A外的一个变量 c 引用。
正是因为每一阶段都存在着引用,所以变量会一直存在不会被清理掉
所以闭包的定义就是
当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包。

闭包的用途
function A() {
    var count = 0; //这里开始产生闭包
    function B() {
       count ++;
       console.log(count);
    }
    return B;
}
var C = A();
C();// 1
C();// 2
C();// 3
C= null; //闭包死亡

看代码可以知道,
count 是函数A 中的一个变量,它的值在函数B 中被改变,函数 B 每执行一次,count 的值就在原来的基础上累加 1 。因此,函数A中的 count 变量会一直保存在内存中。

当我们需要在模块中定义一些变量,并希望这些变量一直保存在内存中但又不会 “污染” 全局的变量时,就可以用闭包来定义这个模块
再看代码

var f = function(document) {
    var viewport;
    var obj = {
        init: function(id) {
            viewport = document.querySelector('#' + id);
        },
        addChild: function(child) {
            viewport.appendChild(child);
        },
        removeChild: function(child) {
            viewport.removeChild(child);
        }
    }
    window.jView = obj;
};
f(document);

在这段代码中似乎看到了闭包的影子,但 f 中没有任何返回值,似乎不具备闭包的条件,注意这句代码:

window.jView = obj;

obj 是在函数 f 中定义的一个对象,这个对象中定义了一系列方法, 执行window.jView = obj
就是在 window 全局对象定义了一个变量 jView,并将这个变量指向 obj 对象,即全局变量 jView 引用了 obj .
而 obj 对象中的函数又引用了函数 f 中的变量 viewport ,因此函数 f 中的 viewport 不会被 GC 回收,viewport 会一直保存到内存中,所以这种写法满足了闭包的条件。
咱们再通过下面代码深刻的了解一下闭包。

function fun(n,o){
	console.log(o)
	return {
		fun: function(m){
			console.log(m,n)
			return fun(m,n)
		}
	}
}
var a= fun(0)
a.fun(1);  //fun(0).fun(1) 
a.fun(2);  // undefind 1,0 0
a.fun(3);
//分析一下代码
首先再调用的外部函数的时候,内部方法也会被调用,产生了闭包,首先调用fun(0),输入o是undefined
然后返回一个函数表达式,就是里面的fun:里面的东西,然后调用里面的函数,传1为参数,这时候m为1,然后n还是为0
然后又返回一个函数,这个函数是外部函数,这样就产生了新的闭包,因为函数内又产生了函数,然后再调用fun(10),最后又输出0

首先确定一下代码里是不是有闭包,就是说有再调用最外部函数的时候,有变量会一直被调用,上面代码n就那个变量,

最后,了解一下内存溢出和内存泄露
1、内存溢出
当运行程序需要的内存超过了剩余的内存,就会抛出内存溢出的错误。
2、内存泄露
占用的内存没有及时释放
内存泄露过多容易导致内存溢出
常见的内存泄露
意外的全局变量 比如没有用var声明变量
没有及时处理的计时器和回调函数
闭包

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值