copy-to源码解析

介绍

copy an object’s properties to another one, include propertiy, getter and setter.

意思是从另一个对象中复制属性,其中包括属性,getter和setter访问器函数。

demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var copy = require('copy-to');

var src = {
_name: 'foo',
set name(val) {
this._name = val;
},
get name() {
return this._name;
},
show: function () {
console.log(this._name);
}
};

var des = {
_name: 'bar'
};

copy(src).to(des);
copy(src).toCover(des);
copy(src).pick('_name', 'name').to(des);
copy(src).pick('_name', 'name').toCover(des);

copy(src).withAccess().and(other).to(des); // 包括构造器属性

源码 copy-to.js 2.0.1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
'use strict';
var slice = Array.prototype.slice;

/**
* Expose copy
*
* ```
* copy({foo: 'nar', hello: 'copy'}).to({hello: 'world'});
* copy({foo: 'nar', hello: 'copy'}).toCover({hello: 'world'});
* ```
*
* @param {Object} src
* @return {Copy}
*/

module.exports = Copy;

/**
* 核心的copy方法
* @param {Object} src
* @param {Boolean} withAccess
*/
function Copy(src, withAccess) {
// 一种写法的兼容,可以直接调用Copy相当于new Copy
if (!(this instanceof Copy)) return new Copy(src, withAccess);
// 设置源对象和目标对象
this.src = src;
this._withAccess = withAccess;
}

/**
* 复制属性包括 getter 和 setter
* @param {[type]} val [description]
* @return {[type]} [description]
*/
Copy.prototype.withAccess = function (w) {
this._withAccess = w !== false;
return this;
};

/**
* 指定 src 对象的某些属性
* @api: public
*/
Copy.prototype.pick = function (keys) {
if (!Array.isArray(keys)) {
keys = slice.call(arguments);
}
if (keys.length) {
this.keys = keys;
}
return this;
};

/**
* copy src to target,
* do not cover any property target has
* @param {Object} to
* @api: public
*/
Copy.prototype.to = function (to) {
to = to || {};

if (!this.src) return to;
var keys = this.keys || Object.keys(this.src);

// _withAccess默认undefined即不考虑构造器,调用
if (!this._withAccess) {
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (to[key] !== undefined) continue;
to[key] = this.src[key];
}
return to;
}

for (var i = 0; i < keys.length; i++) {
var key = keys[i];
// 如果该属性存在跳过,即不覆盖
if (!notDefined(to, key)) continue;
var getter = this.src.__lookupGetter__(key);
var setter = this.src.__lookupSetter__(key);
if (getter) to.__defineGetter__(key, getter);
if (setter) to.__defineSetter__(key, setter);

if (!getter && !setter) {
to[key] = this.src[key];
}
}
return to;
};

/**
* 从src对象复制到to对象,并且覆盖目标对象已有的属性
* @param {Object} to
* @api: public
*/
Copy.prototype.toCover = function (to) {
var keys = this.keys || Object.keys(this.src);

for (var i = 0; i < keys.length; i++) {
var key = keys[i];
delete to[key];
var getter = this.src.__lookupGetter__(key);
var setter = this.src.__lookupSetter__(key);
if (getter) to.__defineGetter__(key, getter);
if (setter) to.__defineSetter__(key, setter);

if (!getter && !setter) {
to[key] = this.src[key];
}
}
};

Copy.prototype.override = Copy.prototype.toCover;

/**
* 添加其他对象到src中
* @param {Obj} obj
* @return {Copy}
*/
Copy.prototype.and = function (obj) {
var src = {};
this.to(src);
this.src = obj;
this.to(src);
this.src = src;

return this;
};

/**
* 检查 obj[key] 是否存在
* @param {Object} obj
* @param {String} key
* @return {Boolean}
*/
function notDefined(obj, key) {
return obj[key] === undefined
&& obj.__lookupGetter__(key) === undefined
&& obj.__lookupSetter__(key) === undefined;
}

__lookupGetter__

该方法会返回当前对象上指定属性的属性读取访问器函数(getter)。目前已废弃,不推荐使用。

__defineGetter__

该方法可以将一个函数绑定在当前对象的指定属性上,当那个属性的值被读取时,你所绑定的函数就会被调用。目前已废弃,不推荐使用。

参考链接:

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

给阿姨来一杯卡普基诺~

支付宝
微信