一、什么是闭包?

    (1)闭包的概念:a、闭包就是函数嵌套时,让局部变量变成自由变量的环境,是一种让局部变量进化的方式。
 
                   b、定义在一个函数内部的函数。
    
    (2)垃圾回收机制:用过一次的东西,先放在一个内存中,不立即删掉,可以随时进行还原或再次使用,直到没有任何作用的时候再清除。
      tip: 如家用电器,电脑回收站。
 
二、闭包的应用场景:
        //1、for循环之中:
// for循环之中的i变量会因为for的循环次数被覆盖,所以在for循环内部存在函数时,而且这个函数内会调用i变量,这种情况下就需要用到闭包。 for (var i = 0; i < 10; i++) {
console.log(i); //可以访问到每次的i
} // 必须满足两个条件:
// 1.在for循环内存在函数
// 2.函数内会调用这个变量 var ali = document.getElementsByTagName("li");
for(var i=0;i<10;i++){
ali[i].onclick = function(){
console.log(i); //在函数内部就无法访问到外部变量
}
} // 如何形成闭包
var ali = document.getElementsByTagName("li");
for(var i=0;i<10;i++){
(function(a){
ali[a].onclick = function(){
console.log(a);
}
})(i)
}
// 一旦内部函数调用外部函数的局部变量,那么这个时候,这个局部变量就会变成内部函数的私有变量 // 2、当需要给setTimeout的回调函数传参时:
setTimeout(function (a){
console.log(a); //两秒后,undefined
}, 2000);
// 或者
setTimeout(fn(10), 2000);
function fn(a){
console.log(a); //没有延迟,直接打印10
} // 怎么使用闭包: function fn(a){
return function(){
console.log(a); //两秒后,10
}
}
var f = fn(10);
setTimeout(f, 2000);

三、闭包的特点:

  (1)闭包是将函数内部和函数外部连接起来的桥梁.

  (2)可以读取函数内部的变量。

  (3)让这些变量的值,始终保存在内存中,不会在调用结束后被系统回收。

  (4)避免全局变量命名空间的污染。

  (5)内存消耗很大,不能滥用。

  (6)闭包会在父函数外部,改变父函数内部变量的值。

四、构造函数继承:

        // 在构造函数中,同样属于两个新创建的函数,也是不相等的
function Fn(name){
this.name = name;
this.show = function(){
alert(this.name);
}
}
var obj1 = new Fn("AAA");
var obj2 = new Fn("BBB");
obj1.show()
obj2.show()
// 此时,任何一个new出来的实例上都有了show方法,可以视为最基础的继承。

五、js中的call和apply继承:

        function Father(skill){
this.skill = skill;
this.show = function(){
alert("我会"+this.skill);
}
}
function Son(abc){
//这里的this指向函数Son的实例化对象
//将Father里面的this改变成指向Son的实例化对象,当相遇将father里面所有的属性和方法都复制到了son身上
//Father.call(this,abc);//继承结束,call适合固定参数的继承
//Father.apply(this,arguments);//继承结束,apply适合不定参数的继承
}
var f = new Father("绝世木匠”);
var s = new Son("一般木匠");
f.show()
s.show();
// 优点:
// 创建子类实例时,可以向父类的构造器传参;
// 缺点:
// 只能继承构造器中定义的属性和方法,不能继承原型上定义的属性和方法

六、js中prototype的概念:

  (1)prototype是原型对象

  (2)指针  constructor  表示当前函数属于谁,用来指向当前原型所属的函数

  (3)原型指针  [[prototype]]  __proto__  相当于一根原型指针,指向当前对象的“父级”

  (4)可以在当前函数的原型身上添加各种属性和方法,以供使用

  (5)JS中万物皆对象,所有内容的指针终点都指向Object

七、原型链继承:

        // 方法一:
Son.prototype = new Father();
//创建一个函数Father,用来做原始对象
function Father(){
this.skill = "铁匠"
};
Father.prototype.show = function(){
console.log(this.skill)
}
//创建一个函数Son,准备继承Father的原型
function Son(){};
//将Son点原型,赋值为一个指针,指向Father的原型
Son.prototype = new Father(); //此时就可以通过执行new Son()获取到从构造函数Father上继承过来属性和方法
var s = new Son()
s.show(); //铁匠 // 优点:
// 1.可以访问父类原型上的方法和属性
// 2.简单方便,易于实现 // 缺点:
// 1.创建子类实例时,无法向父类的构造器传参 // 方法二:
//创建一个函数Father,用来做原始对象
function Father(){
this.skill = "铁匠";
};
Father.prototype.show = function(){
console.log("hello world")
}
//创建一个函数Son,准备继承Father的原型
function Son(){};
//将Son的原型,设置为Father的原型
//Son.prototype = Father.prototype;
//但是这种拷贝方式为对象的浅拷贝,一旦后期修改Son原型上的方法,会影响到Father的原型
//需采用对象的深拷贝方法
for(var i in Father.prototype){
Son.prototype[i] = Father.prototype[i];
}
Son.prototype.show = function(){
console.log("这是子类修改之后的show方法")
}
var f = new Father()
f.show()
var s = new Son()
s.show(); // 优点:
// 完全将父类原型上的方法和属性拷贝到子类原型 // 缺点:
// 只能继承原型上的方法和属性,构造函数无法传参和继承

八、混合继承:

        // 特点:
// 使用call或apply继承父类的构造器中的内容,使用原型继承,继承父类的原型
function Father(skill,id){
this.skill = skill;
this.id = id;
}
Father.prototype.show = function(){
alert("我是father,这是我的技能"+this.skill);
} function Son(){
Father.apply(this,arguments);
}
//如果不做Son的原型继承Father的原型,此时会报错:son.show is not a function
for(var i in Father.prototype){
Son.prototype[i] = Father.prototype[i];
}
//因为,如果不让Son的原型等于Father的原型,Son使用apply是继承不到原型上的方法
Son.prototype.show = function(){
alert("我是son,这是我的技能"+this.skill);
}
var f = new Father("专家级铁匠","father");
var s = new Son("熟练级铁匠","son");
f.show();
s.show();

九、ES6中class的继承:

        class Father{
constructor(){
}
show(){
}
} class Son extends Father{
constructor(){
super()
}
show(){
}
}

十、原型对象相关概念解析:

1、对象中的__proto__是什么:
  js中万物皆对象,每个数据都会有一个__proto__的属性,这个属性叫隐式原型,一个对象(obj)的隐式原型(__proto__)指向构造该对象(obj)的构造函数(object())的原型属性(object.prototype),这样做的原因是为了能够保证实例(obj)能够访问到在构造函数(object())的原型属性(object.prototype)中定义的属性和方法。
 
2、函数中的prototype是什么:
  (1)函数(Function)是一个特殊的对象,除了和其他对象一样有上述__proto__属性之外,还有自己特有的属性——原型(prototype),这个属性被描述成指针,他指向一个对象类型的数据,这个对象的用途就是包含所有将来使用该函数构造出来的可被共享的属性和方法(我们把这个对象叫做原型对象)。
  (2)原型对象内也有一个属性,叫做constructor,这个属性包含了一个指针,指回原函数(类似于arguments.callee。但是arguments只能在函数内部获得,而函数原型对象内的constructor属性,可以在任何能访问到这个函数的位置使用)。
 
3、构造函数,原型,实例之间的关系:
  (1)构造函数Fn身上有属性prototype为原型对象,原型对象内有constructor属性指向当前prototype所在的构造函数Fn。
  (2)在new执行构造函数Fn时,创造了一个实例对象f,实例对象f的__proto__指向构造函数Fn的原型prototype。
  (3)因为实例对象f的__proto__指向构造函数Fn的原型prototype,所以实例对象f可以间接访问到Fn原型prototype的方法。
                                       
4、查看实例对象f是否有指针指向构造函数Fn的原型:
  (1)isPrototypeOf()用于检测两个对象之间似乎否存在这种关系,使用方法如下:
    Fn.prototype.isPrototypeOf(f)    // 查看 Fn 的 prototype 对象,是否是 f 原型
  (2)类似的还有instanceof运算符,使用方法如下:
    console.log(f instanceof Fn)     // 查看 f 对象是否是构造函数 Fn 的实例
    console.log(f instanceof Object)
    tip:两种使用,如果是返回ture,如果不是返回false。
    tip:instanceof运算符右侧为构造函数,并且js中所有原型都来自Object构造函数。
5、javascript中解析器访问属性顺序:
  (1)当访问实例 f 的属性或方法时,会先在当前实例对象 f 中查找,如果没有,则沿着__proto__继续向上寻找,如果找到最顶头的Object还是找不到,则会抛出undefined。如果在实例中找到,或某层原型中找到,就会读取当前值并执行,同时停止向上找寻。
  (2)由此可见,解析器的解析顺序遵循就近原则,如果在最近的位置发现属性存在,便不会继续向上找寻。
 
 
 
 
 
 
 
 
 
 
 
 
 
 

JavaScript中闭包的使用和各种继承介绍的更多相关文章

  1. 在Javascript中闭包(Closure)

    在Javascript中闭包(Closure) 什么是闭包 “官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. ...

  2. javascript中闭包最简单的简绍

    javascript中闭包是什么 JavaScript 变量可以是局部变量或全局变量.私有变量可以用到闭包.闭包就是将函数内部和函数外部连接起来的一座桥梁. 函数的闭包使用场景:比如我们想要一个函数来 ...

  3. 在JavaScript中闭包的作用和简单的用法

    在JavaScript中闭包的作用和简单的用法 一.闭包的简介 作用域链:在js中只有函数有作用域的概念,由于函数内能访问函数外部的数据,而函数外部不能访问函数内部的数据,由上述形成一种作用域访问的链 ...

  4. JavaScript中闭包之浅析解读

    JavaScript中的闭包真心是一个老生常谈的问题了,最近面试也是一直问到,我自己的表述能力又不能完全支撑起来,真是抓狂.在回来的路上,我突然想到了一个很简单的事情,其实我们在做项目时候,其实就经常 ...

  5. 关于javascript中闭包的理解

    闭包就是能够读取其他函数内部变量的函数. 在javascript中,只有函数内部的子函数可以读取局部变量,因此,我理解闭包就是定义在一个函数内部的函数. 例子: var f1 = function() ...

  6. 浅谈JavaScript中闭包

    引言 闭包可以说是JavaScript中最有特色的一个地方,很好的理解闭包是更深层次的学习JavaScript的基础.这篇文章我们就来简单的谈下JavaScript下的闭包. 闭包是什么? 闭包是什么 ...

  7. javascript中闭包的概念

    这个是每个前端工程师绕不开的一个问题,网上各种资料很多,整个春节,我仔细研读了红皮经典中关于这一块的注释,加深了对这一块的理解. 有好几个概念需要重申一下.以下都是我的理解: 1. 闭包是javasc ...

  8. Javascript中闭包的作用域链

    作用域定义了在当前上下文中能够被访问到的成员,在Javascript中分为全局作用域和函数作用域,通过函数嵌套可以实现嵌套作用域. 闭包一般发生在嵌套作用域中.闭包是JavaScript最强大的特性之 ...

  9. JavaScript中闭包实现的私有属性的getter()和setter()方法

    注意: 以下的输出都在浏览器的控制台中 <!DOCTYPE html> <html> <head> <meta charset="utf-8&quo ...

随机推荐

  1. CF 988C Equal Sums 思维 第九题 map

    Equal Sums time limit per test 2 seconds memory limit per test 256 megabytes input standard input ou ...

  2. 如何设置FreePBX的数据库用户可以通过远程来连接Mysql数据库?

    要满足mysql允许通过除了本机外的主机进行使用客户端连接的方法: 要设置root用户允许通过外网用户进行连接访问的操作方法: 1.首先先改mysql的配置文件 将绑定的#bind-address = ...

  3. 【LeetCode】300-最长上升子序列

    题目描述 给定一个无序的整数数组,找到其中最长上升子序列的长度. 示例: 输入: [10,9,2,5,3,7,101,18] 输出: 4 解释: 最长的上升子序列是 [2,3,7,101],它的长度是 ...

  4. 使用FlameGraph火焰图分析JAVA应用性能

    开源项目推荐 Pepper Metrics是我与同事开发的一个开源工具(https://github.com/zrbcool/pepper-metrics),其通过收集jedis/mybatis/ht ...

  5. Springboot源码分析之TypeFilter魔力

    摘要: 在平常的开发中,不知道大家有没有想过这样一个问题,为什么我们自定义注解的时候要使用spring的原生注解(这里指的是类似@Component,@Service........),要么就是 随便 ...

  6. JAVA MAP转实体

    public static <T> T map2Object(Map<String, Object> map, Class<T> clazz) { SimpleDa ...

  7. 配置Linux使用LDAP用户认证

    配置Linux使用LDAP用户认证 本文首发:https://www.cnblogs.com/somata/p/LinuxLDAPUserAuthentication.html 我这里使用的是Cent ...

  8. java8中字符串常量以及GC相应处理机制

    目录 1,常量池 1.1, class文件常量池 1.2, 运行时常量池 1.3,字符串常量池 String.intern() -XX:StringTableSize 2,使用new关键字和使用字符串 ...

  9. JVM垃圾回收?看这一篇就够了!

    深入理解JVM垃圾回收机制 1.垃圾回收需要解决的问题及解决的办法总览 1.如何判定对象为垃圾对象 引用计数法 可达性分析法 2.如何回收 回收策略 标记-清除算法 复制算法 标记-整理算法 分带收集 ...

  10. PHP 扩展开发初探

    什么是 PHP 扩展 通俗说,PHP 扩展是增强 PHP 语言功能的插件.PHP 提供了编程语言的语法,比如分支.循环.函数.类等,这些是 PHP 本身所提供的.在某些情况下需要在 PHP 语言的基础 ...