-
merge mix
-
OOP
- extend
- augment
- aggregate
-
bind rbind
Last active
December 23, 2015 03:08
-
-
Save zhiyelee/6571049 to your computer and use it in GitHub Desktop.
yui oop demos
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var foo = { | |
0: 'foo', | |
1: 'name', | |
2: 'meituan' | |
}; | |
var bar = { | |
0: 'bar', | |
1: 'name', | |
4: 'meituan', | |
length: 3 | |
}; | |
console.log(Array.prototype.slice.call(foo,0)); | |
foo.length = 3; | |
console.log(Array.prototype.slice.call(foo,0)); | |
console.log(Array.prototype.slice.call(bar,0)); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Object.keys which works well in both browser | |
// @source http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation | |
// @discussion http://stackoverflow.com/questions/208016/how-to-list-the-properties-of-a-javascript-object/3937321 | |
Object.keys = Object.keys || (function () { | |
var hasOwnProperty = Object.prototype.hasOwnProperty, | |
hasDontEnumBug = !{toString:null}.propertyIsEnumerable("toString"), | |
DontEnums = [ | |
'toString', | |
'toLocaleString', | |
'valueOf', | |
'hasOwnProperty', | |
'isPrototypeOf', | |
'propertyIsEnumerable', | |
'constructor' | |
], | |
DontEnumsLength = DontEnums.length; | |
return function (o) { | |
if (typeof o != "object" && typeof o != "function" || o === null) | |
throw new TypeError("Object.keys called on a non-object"); | |
var result = []; | |
for (var name in o) { | |
if (hasOwnProperty.call(o, name)) | |
result.push(name); | |
} | |
if (hasDontEnumBug) { | |
for (var i = 0; i < DontEnumsLength; i++) { | |
if (hasOwnProperty.call(o, DontEnums[i])) | |
result.push(DontEnums[i]); | |
} | |
} | |
return result; | |
}; | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// false in node | |
// console.log(this === global); | |
// true in browser | |
// console.log(this === window); | |
// undefined | |
console.log(a); | |
// will throw error | |
// ReferenceError: b is not defined | |
// 去掉下面一行的注释试试 | |
// console.log(b); | |
var a = 10; | |
b = 20; | |
// delete 成功时返回值为true | |
// false | |
console.log(delete a); | |
// here 20 | |
console.log(b); | |
// true, can delete | |
console.log(delete b); | |
// after delete ,still 10 | |
console.log(a); | |
// here error | |
console.log(b); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
Augments the _receiver_ with prototype properties from the _supplier_. The | |
receiver may be a constructor function or an object. The supplier must be a | |
constructor function. | |
If the _receiver_ is an object, then the _supplier_ constructor will be called | |
immediately after _receiver_ is augmented, with _receiver_ as the `this` object. | |
If the _receiver_ is a constructor function, then all prototype methods of | |
_supplier_ that are copied to _receiver_ will be sequestered, and the | |
_supplier_ constructor will not be called immediately. The first time any | |
sequestered method is called on the _receiver_'s prototype, all sequestered | |
methods will be immediately copied to the _receiver_'s prototype, the | |
_supplier_'s constructor will be executed, and finally the newly unsequestered | |
method that was called will be executed. | |
This sequestering logic sounds like a bunch of complicated voodoo, but it makes | |
it cheap to perform frequent augmentation by ensuring that suppliers' | |
constructors are only called if a supplied method is actually used. If none of | |
the supplied methods is ever used, then there's no need to take the performance | |
hit of calling the _supplier_'s constructor. | |
@method augment | |
@param {Function|Object} receiver Object or function to be augmented. | |
@param {Function} supplier Function that supplies the prototype properties with | |
which to augment the _receiver_. | |
@param {Boolean} [overwrite=false] If `true`, properties already on the receiver | |
will be overwritten if found on the supplier's prototype. | |
@param {String[]} [whitelist] An array of property names. If specified, | |
only the whitelisted prototype properties will be applied to the receiver, and | |
all others will be ignored. | |
@param {Array|any} [args] Argument or array of arguments to pass to the | |
supplier's constructor when initializing. | |
@return {Function} Augmented object. | |
@for YUI | |
**/ | |
Y.augment = function (receiver, supplier, overwrite, whitelist, args) { | |
var rProto = receiver.prototype, | |
sequester = rProto && supplier, | |
sProto = supplier.prototype, | |
to = rProto || receiver, | |
copy, | |
newPrototype, | |
replacements, | |
sequestered, | |
unsequester; | |
args = args ? Y.Array(args) : []; | |
if (sequester) { | |
newPrototype = {}; | |
replacements = {}; | |
sequestered = {}; | |
copy = function (value, key) { | |
if (overwrite || !(key in rProto)) { | |
if (toString.call(value) === '[object Function]') { | |
sequestered[key] = value; | |
newPrototype[key] = replacements[key] = function () { | |
return unsequester(this, value, arguments); | |
}; | |
} else { | |
newPrototype[key] = value; | |
} | |
} | |
}; | |
unsequester = function (instance, fn, fnArgs) { | |
// Unsequester all sequestered functions. | |
for (var key in sequestered) { | |
if (hasOwn.call(sequestered, key) | |
&& instance[key] === replacements[key]) { | |
instance[key] = sequestered[key]; | |
} | |
} | |
// Execute the supplier constructor. | |
supplier.apply(instance, args); | |
// Finally, execute the original sequestered function. | |
return fn.apply(instance, fnArgs); | |
}; | |
if (whitelist) { | |
Y.Array.each(whitelist, function (name) { | |
if (name in sProto) { | |
copy(sProto[name], name); | |
} | |
}); | |
} else { | |
Y.Object.each(sProto, copy, null, true); | |
} | |
} | |
Y.mix(to, newPrototype || sProto, overwrite, whitelist); | |
if (!sequester) { | |
supplier.apply(to, args); | |
} | |
return receiver; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// use debug version yui | |
var YUI = require('yui/debug').YUI; | |
YUI().use('oop', 'event-custom-base', function(Y) { | |
// EventTarget in `event-custom-base` | |
var Foo = function() { | |
/* code specific to Foo */ | |
this.publish('interestingMoment'); | |
}; | |
Foo.prototype.doSomething = function() { | |
var eventData = {}; | |
// -- do something interesting, add results to eventData -- | |
eventData.statusText = 'bar'; | |
// notify the subscribers, passing the event data | |
this.fire('interestingMoment', eventData); | |
} | |
Y.augment(Foo, Y.EventTarget); | |
var foo = new Foo(); | |
// add some event listeners | |
foo.on('interestingMoment', function (data) { | |
console.log('I was notified of an interesting moment: ' + data.statusText); | |
}); | |
foo.on('interestingMoment', function (data) { | |
console.log('I was also notified of an interesting moment: ' + data.statusText); | |
}); | |
foo.doSomething(); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var YUI = require('yui').YUI, | |
Y = YUI(); | |
// if no var | |
var maxim = 'Talk is cheap,show me the code'; | |
function foo(f) { | |
this.maxim = 'Code is poetry'; | |
f(); | |
} | |
function bar() { | |
console.log(this.maxim); | |
console.log(this === global); | |
} | |
//maxim = 'Talk is cheap,show me the code'; | |
//bar(1,2,3,4); | |
var obj = { | |
maxim: 'the foolish wait' | |
}; | |
Y.use('oop', function(Y) { | |
foo(bar); | |
foo(Y.bind(bar, obj)); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Utility to set up the prototype, constructor and superclass properties to | |
* support an inheritance strategy that can chain constructors and methods. | |
* Static members will not be inherited. | |
* | |
* @method extend | |
* @param {function} r the object to modify. | |
* @param {function} s the object to inherit. | |
* @param {object} px prototype properties to add/override. | |
* @param {object} sx static properties to add/override. | |
* @return {object} the extended object. | |
*/ | |
Y.extend = function(r, s, px, sx) { | |
if (!s || !r) { | |
Y.error('extend failed, verify dependencies'); | |
} | |
var sp = s.prototype, rp = Y.Object(sp); | |
r.prototype = rp; | |
rp.constructor = r; | |
r.superclass = sp; | |
// assign constructor property | |
if (s != Object && sp.constructor == OP.constructor) { | |
sp.constructor = s; | |
} | |
// add prototype overrides | |
if (px) { | |
Y.mix(rp, px, true); | |
} | |
// add object overrides | |
if (sx) { | |
Y.mix(r, sx, true); | |
} | |
return r; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// use debug version yui | |
var YUI = require('yui').YUI; | |
YUI().use('oop', function(Y) { | |
function People(name) { | |
this.name = name || 'anonymous'; | |
this.canEat = true; | |
} | |
People.prototype.getName = function () { | |
console.log('I am ' + this.name); | |
}; | |
function Teacher() { | |
// can use superclass property to reference parent class | |
Teacher.superclass.constructor.apply(this, arguments); | |
} | |
Y.extend(Teacher, People, { | |
punish: function () { | |
console.log('As a teach, I usually punish students'); | |
} | |
}); | |
var teach = new Teacher(); | |
teach.punish() | |
teach.getName(); | |
console.log('teach.canEat ' + teach.canEat); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Y.merge = function () { | |
var i = 0, | |
len = arguments.length, | |
hasOwn = Object.prototype.hasOwnProperty, | |
result = {}, | |
key, | |
obj; | |
for (; i < len; ++i) { | |
obj = arguments[i]; | |
for (key in obj) { | |
// why not obj.hasOwnProperty(key) | |
if (hasOwn.call(obj, key)) { | |
result[key] = obj[key]; | |
} | |
} | |
} | |
return result; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var YUI = require('yui').YUI, | |
Y, | |
defaultConfig, | |
result; | |
Y = YUI(); | |
defaultConfig = { | |
canDisappear: false, | |
hideWhenNarrow: true | |
}; | |
// 可以merge多个obj,后边的obj的属性会覆盖前边的,未提供配置项 | |
result = Y.merge(defaultConfig, | |
{ canDisappear: true }, | |
{ staticBottomEdge: true }); | |
/* | |
info: | |
{ canDisappear: true, | |
hideWhenNarrow: true, | |
staticBottomEdge: true } | |
*/ | |
Y.log(result); | |
// another demo | |
var foo = { | |
obj: {} | |
}; | |
var copy = Y.merge(foo); | |
//copy.obj.addedToCopy = true; | |
console.log(copy === foo); | |
console.log(copy.obj === foo.obj); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
Mixes _supplier_'s properties into _receiver_. | |
Properties on _receiver_ or _receiver_'s prototype will not be overwritten or | |
shadowed unless the _overwrite_ parameter is `true`, and will not be merged | |
unless the _merge_ parameter is `true`. | |
In the default mode (0), only properties the supplier owns are copied (prototype | |
properties are not copied). The following copying modes are available: | |
* `0`: _Default_. Object to object. | |
* `1`: Prototype to prototype. | |
* `2`: Prototype to prototype and object to object. | |
* `3`: Prototype to object. | |
* `4`: Object to prototype. | |
@method mix | |
@param {Function|Object} receiver The object or function to receive the mixed | |
properties. | |
@param {Function|Object} supplier The object or function supplying the | |
properties to be mixed. | |
@param {Boolean} [overwrite=false] If `true`, properties that already exist | |
on the receiver will be overwritten with properties from the supplier. | |
@param {String[]} [whitelist] An array of property names to copy. If | |
specified, only the whitelisted properties will be copied, and all others | |
will be ignored. | |
@param {Number} [mode=0] Mix mode to use. See above for available modes. | |
@param {Boolean} [merge=false] If `true`, objects and arrays that already | |
exist on the receiver will have the corresponding object/array from the | |
supplier merged into them, rather than being skipped or overwritten. When | |
both _overwrite_ and _merge_ are `true`, _merge_ takes precedence. | |
@return {Function|Object|YUI} The receiver, or the YUI instance if the | |
specified receiver is falsy. | |
**/ | |
Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) { | |
var alwaysOverwrite, exists, from, i, key, len, to; | |
if (!receiver || !supplier) { | |
return receiver || Y; | |
} | |
if (mode) { | |
if (mode === 2) { | |
Y.mix(receiver.prototype, supplier.prototype, overwrite, | |
whitelist, 0, merge); | |
} | |
from = mode === 1 || mode === 3 ? supplier.prototype : supplier; | |
to = mode === 1 || mode === 4 ? receiver.prototype : receiver; | |
if (!from || !to) { | |
return receiver; | |
} | |
} else { | |
from = supplier; | |
to = receiver; | |
} | |
alwaysOverwrite = overwrite && !merge; | |
if (whitelist) { | |
for (i = 0, len = whitelist.length; i < len; ++i) { | |
key = whitelist[i]; | |
if (!hasOwn.call(from, key)) { | |
continue; | |
} | |
exists = alwaysOverwrite ? false : key in to; | |
if (merge && exists && isObject(to[key], true) | |
&& isObject(from[key], true)) { | |
Y.mix(to[key], from[key], overwrite, null, 0, merge); | |
} else if (overwrite || !exists) { | |
to[key] = from[key]; | |
} | |
} | |
} else { | |
for (key in from) { | |
// duplication,same as above,for performance tradeoff | |
} | |
if (Y.Object._hasEnumBug) { | |
Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge); | |
} | |
} | |
return receiver; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var YUI = require('yui').YUI, | |
Y = YUI(); | |
function Person(name) { | |
this.name = 'init person'; | |
this.eat = function() { | |
console.log(this.name + "is eating."); | |
}; | |
} | |
Person.prototype.sleep = function() { | |
console.log(this.name + "is sleeping."); | |
}; | |
function Manong(name) { | |
this.name = name; | |
} | |
Manong.prototype.coding = function () { | |
console.log(this.name + "is coding."); | |
}; | |
// mode 1 | |
Y.mix(Manong, Person, true, null, 1); | |
// [Function: Manong] | |
console.log(Manong); | |
// { coding: [Function], sleep: [Function] } | |
console.log(Manong.prototype); | |
// // mod2 | |
// Person.pattr1 = "person attr1"; | |
// Manong.mattr1 = "manong attr1"; | |
// Y.mix(Manong, Person, true, null, 2); | |
// // { [Function: Manong] mattr1: 'manong attr1', pattr1: 'person attr1' } | |
// console.log(Manong); | |
// // { coding: [Function], sleep: [Function] } | |
// console.log(Manong.prototype); | |
// // mod3 | |
// Y.mix(Manong, Person, true, null, 3); | |
// // { [Function: Manong] sleep: [Function] } | |
// console.log(Manong); | |
// // { coding: [Function] } | |
// console.log(Manong.prototype); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment