| 
<?php 
 /**
 * Class JSObject
 * @author  kevy <kevmt.com>
 * @license MIT License!
 */
 
 /*!
 
 usage:
 
 $Cat = new JSObject([
 'name' => 'Tom',
 'alias' => 'the cat.',
 'who' => function () {
 return $this->name . ' alias ' . $this->alias;
 }
 ]);
 
 echo $Cat->who(); // Tom alias the cat.
 
 $Mouse = new JSObject(function () {
 $this->name = 'Jerry';
 $this->alias = 'the mouse.';
 $this->who = function () {
 return $this->name . ' alias ' . $this->alias;
 }
 });
 
 echo $Mouse->who(); // Jerry alias the mouse.
 
 */
 class JSObject
 {
 /**
 * JSObject constructor.
 * @param array|closure $opt
 */
 function __construct($opt = NULL)
 {
 $_call = null;
 
 if (is_array($opt) && !empty($opt)) {
 foreach ($opt as $name => $value) {
 $this->$name = $value;
 }
 if (isset($this->_init) &&
 (is_object($this->_init) && $this->_init instanceof Closure)
 ) {
 // bind to this object, so we can use `$this`
 $_call = $this->_init->bindTo($this);
 }
 } else {
 if (is_object($opt) && $opt instanceof Closure) {
 // bind to this object, so we can use `$this`
 $_call = $opt->bindTo($this);
 }
 }
 
 if (isset($_call)) {
 $rVal = $_call();
 if (!empty($rVal)) {
 return $rVal;
 }
 }
 
 return $this;
 }
 
 /**
 * @param $name
 * @param $args
 * @return mixed
 */
 function __call($name, $args)
 {
 if (is_callable($this->$name)) {
 if ($this->$name instanceof Closure) {
 // bind to this object, so we can use `$this`
 $_fn = $this->{$name}->bindTo($this);
 } else {
 $_fn = $this->{$name};
 }
 return call_user_func_array($_fn, $args);
 }
 }
 }
 |