jQuery技术

前端进阶(十一):详细图解jQuery对象(5)

字号+ 作者:H5之家 来源:H5之家 2017-04-07 17:03 我要评论( )

关于上面例子中,函数表达式中的赋值操作,在其他一些地方也会被经常使用,我们清楚其中的关系即可。 在构造函数中添加方法function Person(name) {this.name = name;this.age = age;// 在构造函数内部中添加方法th

关于上面例子中,函数表达式中的赋值操作,在其他一些地方也会被经常使用,我们清楚其中的关系即可。

在构造函数中添加方法 function Person(name) { this.name = name; this.age = age; // 在构造函数内部中添加方法 this.getAge = function() { return this.age; } this. } // 给原型添加方法 Person.prototype.getName = function() { return this.name; } // 在对象中添加方法 var a = { m: 20, getM: function() { return this.m; } }

匿名函数

在上面我们大概讲述了函数表达式中的赋值操作。而匿名函数,顾名思义,就是指的没有被显示进行赋值操作的函数。它的使用场景,多作为一个参数传入另一个函数中。

var a = 10; var fn = function(bar, num) { return bar() + num; } fn(function() { return a; }, 20)

在上面的例子中,fn的第一个参数传入了一个匿名函数。虽然该匿名函数没有显示的进行赋值操作,我们没有办法在外部执行上下文中引用到它,但是在fn函数内部,我们将该匿名函数赋值给了变量bar,保存在了fn变量对象的arguments对象中。

// 变量对象在fn上下文执行过程中的创建阶段 VO(fn) = { arguments: { bar: undefined, num: undefined, length: 2 } } // 变量对象在fn上下文执行过程中的执行阶段 // 变量对象变为活动对象,并完成赋值操作与执行可执行代码 VO -> AO AO(fn) = { arguments: { bar: function() { return a }, num: 20, length: 2 } }

由于匿名函数传入另一个函数之后,最终会在另一个函数中执行,因此我们也常常称这个匿名函数为回调函数。关于匿名函数更多的内容,我会在下一篇深入探讨柯里化的文章中进行更加详细讲解。

匿名函数的这个应用场景几乎承担了函数的所有难以理解的知识点,因此我们一定要对它的这些细节了解的足够清楚,如果对于变量对象的演变过程你还看不太明白,一定要回过头去看这篇文章:前端基础进阶(三):变量对象详解

函数自执行与块级作用域

在ES5中,没有块级作用域,因此我们常常使用函数自执行的方式来模仿块级作用域,这样就提供了一个独立的执行上下文,结合闭包,就为模块化提供了基础。

(function() { // ... })();

一个模块往往可以包括:私有变量、私有方法、公有变量、公有方法。

根据作用域链的单向访问,外面可能很容易知道在这个独立的模块中,外部执行环境是无法访问内部的任何变量与方法的,因此我们可以很容易的创建属于这个模块的私有变量与私有方法。

(function() { // 私有变量 var age = 20; var name = 'Tom'; // 私有方法 function getName() { return `your name is ` + name; } })();

但是共有方法和变量应该怎么办?大家还记得我们前面讲到过的闭包的特性吗?没错,利用闭包,我们可以访问到执行上下文内部的变量和方法,因此,我们只需要根据闭包的定义,创建一个闭包,将你认为需要公开的变量和方法开放出来即可。

如果你对闭包了解不够,前端基础进阶(四):详细图解作用域链与闭包应该可以帮到你。

(function() { // 私有变量 var age = 20; var name = 'Tom'; // 私有方法 function getName() { return `your name is ` + name; } // 共有方法 function getAge() { return age; } // 将引用保存在外部执行环境的变量中,形成闭包,防止该执行环境被垃圾回收 window.getAge = getAge; })();

当然,闭包在模块中的重要作用,我们也在讲解闭包的时候已经强调过,但是这个知识点真的太重要,需要我们反复理解并且彻底掌握,因此为了帮助大家进一步理解闭包,我们来看看jQuery中,是如何利用我们模块与闭包的。

// 使用函数自执行的方式创建模块 (function(window, undefined) { // 声明jQuery构造函数 var jQuery = function(name) { // 主动在构造函数中,返回一个jQuery实例 return new jQuery.fn.init(name); } // 添加原型方法 jQuery.prototype = jQuery.fn = { constructor: jQuery, init:function() { ... }, css: function() { ... } } jQuery.fn.init.prototype = jQuery.fn; // 将jQuery改名为$,并将引用保存在window上,形成闭包,对外开发jQuery构造函数,这样我们就可以访问所有挂载在jQuery原型上的方法了 window.jQuery = window.$ = jQuery; })(window); // 在使用时,我们直接执行了构造函数,因为在jQuery的构造函数中通过一些手段,返回的是jQuery的实例,所以我们就不用再每次用的时候在自己new了 $('#p1');

在这里,我们只需要看懂闭包与模块的部分就行了,至于内部的原型链是如何绕的,为什么会这样写,我在讲面向对象的时候会为大家慢慢分析。举这个例子的目的所在,就是希望大家能够重视函数,因为在实际开发中,它无处不在。

接下来我要分享一个高级的,非常有用的模块的应用。当我们的项目越来越大,那么需要保存的数据与状态就越来越多,因此,我们需要一个专门的模块来维护这些数据,这个时候,有一个叫做状态管理器的东西就应运而生。对于状态管理器,最出名的,我想非redux莫属了。虽然对于还在学习中的大家来说,redux是一个有点高深莫测的东西,但是在我们学习之前,可以先通过简单的方式,让大家大致了解状态管理器的实现原理,为我们未来的学习奠定坚实的基础。

先来直接看代码。

// 自执行创建模块 (function() { // states 结构预览 // states = { // a: 1, // b: 2, // m: 30, // o: {} // } var states = {}; // 私有变量,用来存储状态与数据 // 判断数据类型 function type(elem) { if(elem == null) { return elem + ''; } return toString.call(elem).replace(/[\[\]]/g, '').split(' ')[1].toLowerCase(); } /** * @Param name 属性名 * @Description 通过属性名获取保存在states中的值 */ function get(name) { return states[name] ? states[name] : ''; } function getStates() { return states; } /* * @param options {object} 键值对 * @param target {object} 属性值为对象的属性,只在函数实现时递归中传入 * @desc 通过传入键值对的方式修改state树,使用方式与小程序的data或者react中的setStates类似 */ function set(options, target) { var keys = Object.keys(options); var o = target ? target : states; keys.map(function(item) { if(typeof o[item] == 'undefined') { o[item] = options[item]; } else { type(o[item]) == 'object' ? set(options[item], o[item]) : o[item] = options[item]; } return item; }) } // 对外提供接口 window.get = get; window.set = set; window.getStates = getStates; })() // 具体使用如下 set({ a: 20 }); // 保存 属性a set({ b: 100 }); // 保存属性b set({ c: 10 }); // 保存属性c // 保存属性o, 它的值为一个对象 set({ o: { m: 10, n: 20 } }) // 修改对象o 的m值 set({ o: { m: 1000 } }) // 给对象o中增加一个c属性 set({ o: { c: 100 } }) console.log(getStates())

demo实例在线地址

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 前端基础进阶(十一):详细图解jQuery对象,以及如何扩展jQuery

    前端基础进阶(十一):详细图解jQuery对象,以及如何扩展jQuery

    2017-03-25 10:00

网友点评
'