JavaScript面向对象核心知识与概念归纳整理(2)

实用闭包主要是为了设计私有方法和变量。闭包的优点是可以避免全局变量的污染;缺点是闭包会常驻内存,增加内存使用量,使用不当很容易造成内存泄露。在JavaScript中,函数即闭包,只有函数才能产生作用域。

闭包有3个特性:

函数嵌套函数

在函数内部可以引用外部的参数和变量

参数和变量不会以垃圾回收机制回收

4.2 闭包有什么用(特性)

闭包的作用,就是保存自己私有的变量,通过提供的接口(方法)给外部使用,但外部不能直接访问该变量。
通过使用闭包,我们可以做很多事情,比如模拟面向对象的代码风格;更优雅,更简洁的表达出代码;在某些方面提升代码的执行效率。利用闭包可以实现如下需求:

匿名自执行函数

一个匿名的函数,并立即执行它,由于外部无法引用它内部的变量,因此在执行完后很快就会被释放,关键是这种机制不会污染全局对象。

缓存

闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。

实现封装

模拟面向对象的代码风格

4.3 闭包的基本模型

对象模式
函数内部定义个一个对象,对象中绑定多个函数(方法),返回对象,利用对象的方法访问函数内的数据

function createPerson() { var __name__ = ""; return { getName: function () { return __name__; }, setName: function( value ) { // 如果不姓张就报错 if ( value.charAt(0) === '张' ) { __name__ = value; } else { throw new Error( '姓氏不对,不能取名' ); } } } } var p = createPerson(); p.set_Name( '张三丰' ); console.log( p.get_Name() ); p.set_Name( '张王富贵' ); console.log( p.get_Name() );

函数模式
函数内部定义一个新函数,返回新函数,用新函数获得函数内的数据

function foo() { var num = Math.random(); function func() { return mun; } return func; } var f = foo(); // f 可以直接访问这个 num var res1 = f(); var res2 = f();

沙箱模式
沙箱模式就是一个自调用函数,代码写到函数中一样会执行,但是不会与外界有任何的影响,比如jQuery

(function () { var jQuery = function () { // 所有的算法 } // .... // .... jQuery.each = function () {} window.jQuery = window.$ = jQuery; })(); $.each( ... )

4.4 闭包的性能问题

js 垃圾回收机制,也就是当一个函数被执行完后,其作用域会被收回,如果形成了闭包,执行完后其作用域就不会被收回。

函数执行需要内存,那么函数中定义的变量,会在函数执行结束后自动回收,凡是因为闭包结构的,被引出的数据,如果还有变量引用这些数据的话,那么这些数据就不会被回收。因此在使用闭包的时候如果不使用某些数据了,一定要赋值一个null

var f = (function () { var num = 123; return function () { return num; }; })(); // f 引用着函数,函数引用着变量num // 因此在不使用该数据的时候,最好写上 f = null;

五、原型 5.1 什么是原型

一句话说明什么是原型:原型能存储我们的方法,构造函数创建出来的实例对象能够引用原型中的方法。

JS中一切皆对象,而每个对象都有一个原型(Object除外),这个原型,大概就像Java中的父类,所以,基本上你可以认为原型就是这个对象的父对象,即每一个对象(Object除外)内部都保存了它自己的父对象,这个父对象就是原型。一般创建的对象如果没有特别指定原型,那么它的原型就是Object(这就很类似Java中所有的类默认继承自Object类)。

ES6通过引入class ,extends等关键字,以一种语法糖的形式把构造函数包装成类的概念,更便于大家理解。是希望开发者不再花精力去关注原型以及原型链,也充分说明原型的设计意图和类是一样的。

5.2 查看对象的原型

当对象被创建之后,查看它们的原型的方法不止一种,以前一般使用对象的__proto__属性,ES6推出后,推荐用Object.getPrototypeOf()方法来获取对象的原型

function A(){ this.name='lala'; } var a=new A(); console.log(a.__proto__) //输出:Object {} //推荐使用这种方式获取对象的原型 console.log(Object.getPrototypeOf(a)) //输出:Object {}

无论对象是如何创建的,默认原型都是Object,在这里需要提及的比较特殊的一点就是,通过构造函数来创建对象,函数A本身也是一个对象,而A有两个指向表示原型的属性,分别是__proto__和prototype,而且两个属性并不相同

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/ae0a310d791581ed9286b871cb4f5bd1.html