js面向对象原型和继承作用域链和闭包
原型
我们都知道,函数创建时浏览器会在内存中创建一个对象。很多人在这里都感觉很难理解里面的关系
函数创建的时候,浏览器会在内存中创建一个由prototype指向的对象。其实只有当你要将函数作为构造函数使用的时候,创建出来的对象才会发挥作用。
例如:
var obj=new People();
的时候,obj对象就不仅仅使用自己的属性和方法,它也可以使用People函数创建时生成prototype对象的方法。
而且,Prople的prototype的属性和方法可以通过 Prople.prototype.属性名或者方法名创建。
那么也就是说用这种方法可以是对象所使用的属性和方法更多。
还有一个好处就是减少代码的重复。当多个对象的属性或方法相同时,那么让他们都new一下构造函数。则可以不用每个对象都加上this.属性。
原型链,继承
原型链
字面理解就是有原型形成的链,让一个函数的原型等于另一个函数,那么这个函数就另一个函数通过原型串在一起,形成链。这样的方法就可以把n个函数串在一起。
继承
函数1——>prototype=函数2——>prototype=函数3——>prototype........
按照这样的链,函数1可以通过链访问函数2,函数3等等N个函数,这样就是继承。
作用域链
要连接作用域链,先要知道什么是执行环境。执行环境通俗来讲就是代码要执行的环境,也就是告诉你,环境了有什么,变量,方法之类的,可是使用的对象。最简单的例子就是全局执行环境,也就是window,所有写在js的方法,都在window执行环境里。
而每一个函数也有自己的执行环境。
而作用域链,可以看做是起作用的链,每个函数在创建的时候,都有执行环境,而众多的函数形成的执行环境会存储在作用域链中,因此作用域链就是存储函数执行环境的。
函数要使用对象的时候,是在作用域链中查找的。查找的顺序是顶层开始的。
存入的时候都是全局执行环境在顶层的,但是,但函数调用执行的时候,会先提前到顶层,执行完在释放。所以可以理解为函数的查找是在自身,当没找到则完上层查找,直到找到为止。
闭包
就是有权访问另一函数作用域的变量的函数就是闭包。当然了,访问window的作用域变量是不算的。(函数嵌套肯定就是闭包了,因为里面的函数肯定可以访问外面函数作用域的变量)。
闭包的经典问题
先看看这段代码:
var li=document.querySelectorAll('li');
function a(){
for(var i=0;i<li.length;i++){
li[i].onclick=function(){
console.log(i);
}
}
}
输出结果为点击出现的全是li.length。要的效果是点击第一个li出现0...
第一种方法:
var li=document.querySelectorAll('li');
function a(){
for(var i=0;i<li.length;i++){
li[i].index=i;
li[i].onclick=function(){
console.log(li[i].index);
}
}
}
第二种方法:
var li=document.querySelectorAll('li');
function a(){
for(var i=0;i<li.length;i++){
li[i].onclick=(function(i){
return function(){
console.log(i);
}
})(i)
}
}
第三种方法:
var li=document.querySelectorAll('li');
function a(){
for(let i=0;i<li.length;i++){
li[i].onclick=function(){
console.log(i);
}
}
}