├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── cjs └── index.js ├── esm └── index.js ├── index.js ├── min.js ├── package.json └── test └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | coverage/ 4 | package-lock.json 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | coverage/* 2 | node_modules/* 3 | test/* 4 | _config.yml 5 | .DS_Store 6 | .gitignore 7 | .travis.yml 8 | package-lock.json 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - stable 4 | git: 5 | depth: 1 6 | branches: 7 | only: 8 | - master 9 | - /^greenkeeper/.*$/ 10 | after_success: 11 | - "npm run coveralls" 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2019, Andrea Giammarchi, @WebReflection 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 10 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 12 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 | OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 | PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # factory-knows 🏭👃 2 | 3 | [![Build Status](https://travis-ci.com/WebReflection/factory-knows.svg?branch=master)](https://travis-ci.com/WebReflection/factory-knows) [![Coverage Status](https://coveralls.io/repos/github/WebReflection/factory-knows/badge.svg?branch=master)](https://coveralls.io/github/WebReflection/factory-knows?branch=master) [![Greenkeeper badge](https://badges.greenkeeper.io/WebReflection/factory-knows.svg)](https://greenkeeper.io/) ![WebReflection status](https://offline.report/status/webreflection.svg) 4 | 5 | An `instanceof` alternative for non class based, factory oriented, programming. 6 | 7 | ```js 8 | import $ from 'factory-knows'; 9 | // OR 10 | // const $ = require('factory-knows'); 11 | // OR 12 | // 13 | // 14 | 15 | const Person = $((name = 'anonymous') => ({ 16 | birthday() { 17 | this.age++; 18 | console.log('🎉'); 19 | }, 20 | age: 0, 21 | name 22 | })); 23 | 24 | const me = Person('A G'); 25 | Person.knows(me); // true 26 | me.birthday(); // 🎉 27 | 28 | const {assign} = Object; 29 | const Employee = $((company, name) => assign( 30 | Person(name), 31 | { 32 | levelUP() { 33 | this.experience++; 34 | console.log('🤝'); 35 | }, 36 | experience: 0, 37 | company 38 | } 39 | )); 40 | 41 | const roadrunner = Employee('ACME', 'RoadRunner'); 42 | Person.knows(roadrunner); // true 43 | Employee.knows(roadrunner); // true 44 | roadrunner.levelUP(); // 🤝 45 | roadrunner.experience; // 1 46 | ``` -------------------------------------------------------------------------------- /cjs/index.js: -------------------------------------------------------------------------------- 1 | /*! (c) Andrea Giammarchi - ISC */ 2 | function factoryKnows(fn) { 3 | // it should be a WeakSet, but IE11 has only a WeakMap so ... KISS 4 | // pony/polyfill available here: https://github.com/ungap/weakmap#weakmap 5 | var knowledge = new WeakMap; 6 | return Object.defineProperty( 7 | function () { 8 | var value = fn.apply(this, arguments); 9 | knowledge.set(value, true); 10 | return value; 11 | }, 12 | 'knows', 13 | {value: knowledge.has.bind(knowledge)} 14 | ); 15 | } 16 | module.exports = factoryKnows; 17 | -------------------------------------------------------------------------------- /esm/index.js: -------------------------------------------------------------------------------- 1 | /*! (c) Andrea Giammarchi - ISC */ 2 | function factoryKnows(fn) { 3 | // it should be a WeakSet, but IE11 has only a WeakMap so ... KISS 4 | // pony/polyfill available here: https://github.com/ungap/weakmap#weakmap 5 | var knowledge = new WeakMap; 6 | return Object.defineProperty( 7 | function () { 8 | var value = fn.apply(this, arguments); 9 | knowledge.set(value, true); 10 | return value; 11 | }, 12 | 'knows', 13 | {value: knowledge.has.bind(knowledge)} 14 | ); 15 | } 16 | export default factoryKnows; 17 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /*! (c) Andrea Giammarchi - ISC */ 2 | function factoryKnows(fn) { 3 | // it should be a WeakSet, but IE11 has only a WeakMap so ... KISS 4 | // pony/polyfill available here: https://github.com/ungap/weakmap#weakmap 5 | var knowledge = new WeakMap; 6 | return Object.defineProperty( 7 | function () { 8 | var value = fn.apply(this, arguments); 9 | knowledge.set(value, true); 10 | return value; 11 | }, 12 | 'knows', 13 | {value: knowledge.has.bind(knowledge)} 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /min.js: -------------------------------------------------------------------------------- 1 | /*! (c) Andrea Giammarchi - ISC */ 2 | function factoryKnows(e){var r=new WeakMap;return Object.defineProperty(function(){var n=e.apply(this,arguments);return r.set(n,!0),n},"knows",{value:r.has.bind(r)})} -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "factory-knows", 3 | "version": "0.1.2", 4 | "description": "An instanceof alternative for non class based, factory oriented, programming.", 5 | "main": "index.js", 6 | "module": "esm/index.js", 7 | "unpkg": "min.js", 8 | "scripts": { 9 | "build": "npm run esm && npm run cjs && npm run min && npm test", 10 | "cjs": "cp index.js cjs/ && echo 'module.exports = factoryKnows;' >> cjs/index.js", 11 | "coveralls": "cat ./coverage/lcov.info | coveralls", 12 | "esm": "cp index.js esm/ && echo 'export default factoryKnows;' >> esm/index.js", 13 | "min": "uglifyjs index.js --support-ie8 --comments=/^!/ -c -m -o min.js", 14 | "test": "istanbul cover test/index.js" 15 | }, 16 | "keywords": [ 17 | "factory", 18 | "functional", 19 | "instanceof", 20 | "alternative" 21 | ], 22 | "author": "Andrea Giammarchi", 23 | "license": "ISC", 24 | "devDependencies": { 25 | "coveralls": "^3.0.3", 26 | "istanbul": "^0.4.5", 27 | "uglify-js": "^3.4.9" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | var $ = require('../cjs'); 2 | 3 | var Valuable = $((value = '') => ({ 4 | append(obj) { 5 | if (Valuable.knows(obj)) 6 | this.value += obj.value; 7 | else 8 | this.value += String(obj); 9 | }, 10 | value 11 | })); 12 | 13 | var valuable = Valuable('a'); 14 | valuable.append('b'); 15 | valuable.append(Valuable('c')); 16 | console.assert(valuable.value === 'abc', 'Valuable works'); 17 | 18 | var Extended = $((value = '') => 19 | Object.assign( 20 | Valuable(value), 21 | { 22 | prepend(obj) { 23 | if (Extended.knows(obj)) 24 | this.value = obj.value + this.value; 25 | else 26 | this.value = String(obj) + this.value; 27 | } 28 | } 29 | ) 30 | ); 31 | 32 | var extended = Extended('b'); 33 | extended.append(Extended('c')); 34 | extended.prepend(Extended('a')); 35 | console.assert(extended.value === 'abc', 'Extended works'); 36 | 37 | var Super = $((value = '') => { 38 | var object = Extended(value); 39 | var {append} = object; // ◀━━┓ that 🎉🎉🎉 40 | return Object.assign(object, { // ┃ 41 | append(obj) { // ◀━/┫ not that ⚠️ 42 | console.log('with super append'); // ┃ 43 | append.apply(object, arguments); // ━━━┛ 44 | }, 45 | prepend(obj) { 46 | if (Valuable.knows(obj)) 47 | this.value = obj.value + this.value; 48 | else 49 | this.value = String(obj) + this.value; 50 | } 51 | }); 52 | }); 53 | 54 | var superior = Super('b'); 55 | superior.append(Super('c')); 56 | superior.prepend(Super('a')); 57 | console.assert(superior.value === 'abc', 'Super works'); 58 | --------------------------------------------------------------------------------