内容:
- jQuery无new构建实例
- 共享原型设计
- extend源码解析


jQuery的Extend用法:
var obj1 = {name: 'Max',list: {age: 21}};var obj2 = {items: {nan: 'Ch'},list: {gender: 'Male'}};// 给任意对象扩展属性var obj3 = $.extend(true, obj1, obj2);console.log(obj3);// 给jQuery本身扩展属性jQuery.extend({work: function() {}});jQuery.work();// 给jQuery对象实例扩展属性jQuery.fn.extend({gender: 'Male'});jQuery('').gender;
Code实现:
(function(root) {var jQuery = function() {return new jQuery.prototype.init(); // 创建jQuery的实例对象,不能写 new jQuery(),会造成循环调用}// jQuery原型上扩展属性jQuery.fn = jQuery.prototype = {init: function() {},css: function() {}};// jQuery本身扩展和原型上扩展都调用了同一个方法 extendjQuery.fn.extend = jQuery.extend = function(){var target = arguments[0] || {};var length = arguments.length;var i = 1;var deep = false;var name, option, copy, src,isCopyArray, clone;// 第一个参数是否为布尔类型:target要为第二个参数,i要从第三个参数开始循环if(typeof target === "boolean") {deep = target;target = arguments[1];i = 2;}// 第一个参数必须是objectif(typeof target !== 'object') {target = {};}if(i === length) {target = this;i--;}// 浅拷贝, 深拷贝//1.扩展:target = this; i = 0;length=1;//2.浅拷贝:target = arguments[0];i=1;//3.深拷贝:target = arguments[1];i=2;for(; i < length; i++) {if((option = arguments[i]) !== null) {for(name in option) {copy = option[name];src = target[name];if (deep && (jQuery.isPlainObject(copy) || (isCopyArray = jQuery.isArray(copy)))) {if(isCopyArray) {isCopyArray = false;clone = src && jQuery.isArray(src) ? src : [];}else {clone = src && jQuery.isPlainObject(src) ? src : {};}target[name] = jQuery.extend(deep, clone, copy);}else {target[name] = option[name];}}}}return target;}// 共享原型设计:init的原型等于jQuery的原型,这样new init()创建出来对象的原型也就是jQuery的原型jQuery.fn.init.prototype = jQuery.fn;jQuery.extend({isPlainObject: function(obj) {return toString.call(obj) === "[object Object]";},isArray: function(obj) {return toString.call(obj) === "[object Array]";}});root.$ = root.jQuery = jQuery; // $是jQuery的一个别名})(this);
思考问题:
1. jQuery实际是new jQuery.fn.init()实例化对象,那么常用的方法如$.ajax,$.get是怎么实现的?
A: ajax,get等都是jQuery的静态方法;通过 jQuery.extend({ajax:…, get: ….}) 去实现;
$.extend()与$.fn.extend()的区别?
$.extend() 是向 jQuery上扩展属性,$.fn.extend() 是向jQuery的实例对象上扩展属性;可以参考下面的Code。
通过$.extend()扩展的属性,要通过jQuery.属性名来访问;
通过$.fn.extend()扩展的属性,要通过jQuery(‘selector’).属性名来访问(也就是通过jQuery的实例对象访问)。// 给jQuery本身扩展属性jQuery.extend({work: function() {}});jQuery.work();// 给jQuery对象实例扩展属性jQuery.fn.extend({gender: 'Male'});jQuery('').gender;
具体例子可以参考:
https://www.yuque.com/niruoanhao/cc61zh/qgw5re
1. JSON.stringify和JSON.parse() (深拷贝)
var x = {a: 1,b: undefined,c: null,d: function() {},e: Symbol,f: new Date,}var y = JSON.parse(JSON.stringify(x));console.log(y) /*{a: 1c: nullf: "2019-08-30T07:11:45.286Z"}*/
这种拷贝方法会造成值为undefined、Symbol、function的属性丢失,如果确定要拷贝的对象没有这几类值的话就放心大胆的使用吧。
2. 扩展符…
var x = {a: 1,b: {c: 1}}var y = {...x};y.a = 13;y.b.c = 15;console.log(x) // x:{a:1,b:{c:15}}
这个结果是不是似曾相识,这和我们前面写的浅拷贝一模一样哦,所以 … 可以用来拷一层结构的数据,多层的话就得谨慎使用了。
3. object.assign
var m1 = {a:1,b:{x:1,y:2}};var n1 = {b:{x1:3,y1:4}};var obj1 = Object.assign(m1,n1) //obj1:{a:1,b:{x1:3,y1:4}}
浅拷贝。
思维扩展
我们使用拷贝的目的是复制一份,原来的对象保持不变,之前一直围绕如何让复制出来对象与原对象取消关联,是否可以换个思路,如冻结原对象。
freeze
var x = {a: 1,b:{c:1}}var y = x;Object.freeze(x);y.a = 2;console.log(x, y) // x:{a:1} y:{a:1}
第一个尝试案例就失败了,x,y指向同一个指针,而这个指针索引的对象被冻结,导致y的修改是无效的。经过尝试freeze只能冻结第一层结构,如x.b.c是没有冻结的,可以改变,如果想深度冻结一个对象,可以和深拷贝一样使用递归冻结。
