2021SC@SDUSC

#pragma once
#include <cstdlib>
#include <string>
#include <unordered_map>
#include <vector>

namespace hippy {
namespace base {

class JSValueWrapper final {
 public:
  using JSObjectType = typename std::unordered_map<std::string, JSValueWrapper>;
  using JSArrayType = typename std::vector<JSValueWrapper>;
  enum class Type {
    Undefined,
    Null,
    Boolean,
    Int32,
    UInt32,
    Double,
    String,
    Object,
    Array
  };

 public:
  static JSValueWrapper Undefined();
  static JSValueWrapper Null();

 public:
  JSValueWrapper() {}
  JSValueWrapper(const JSValueWrapper& source);

  JSValueWrapper(int32_t int32_value)  // NOLINT
      : type_(Type::Int32), int32_value_(int32_value) {}
  JSValueWrapper(uint32_t uint32_value)  // NOLINT
      : type_(Type::UInt32), uint32_value_(uint32_value) {}
  JSValueWrapper(double double_value)  // NOLINT
      : type_(Type::Double), double_value_(double_value) {}
  JSValueWrapper(bool bool_value)  // NOLINT
      : type_(Type::Boolean), bool_value_(bool_value) {}
  explicit JSValueWrapper(std::string&& string_value)
      : type_(Type::String), string_value_(std::move(string_value)) {}
  explicit JSValueWrapper(const std::string& string_value)
      : type_(Type::String), string_value_(string_value) {}
  JSValueWrapper(const char* string_value)  // NOLINT
      : type_(Type::String), string_value_(std::string(string_value)) {}
  JSValueWrapper(const char* string_value, size_t length)
      : type_(Type::String), string_value_(std::string(string_value, length)) {}
  explicit JSValueWrapper(JSObjectType&& object_value)
      : type_(Type::Object), object_value_(std::move(object_value)) {}
  explicit JSValueWrapper(const JSObjectType& object_value)
      : type_(Type::Object), object_value_(object_value) {}
  explicit JSValueWrapper(JSArrayType&& array_value)
      : type_(Type::Array), array_value_(array_value) {}
  explicit JSValueWrapper(JSArrayType& array_value)
      : type_(Type::Array), array_value_(array_value) {}
  ~JSValueWrapper();

 public:
  JSValueWrapper& operator=(const JSValueWrapper& rhs) noexcept;
  JSValueWrapper& operator=(const int32_t rhs) noexcept;
  JSValueWrapper& operator=(const uint32_t rhs) noexcept;
  JSValueWrapper& operator=(const double rhs) noexcept;
  JSValueWrapper& operator=(const bool rhs) noexcept;
  JSValueWrapper& operator=(const std::string& rhs) noexcept;
  JSValueWrapper& operator=(const char* rhs) noexcept;
  JSValueWrapper& operator=(const char16_t* rhs) noexcept;
  JSValueWrapper& operator=(const JSObjectType& rhs) noexcept;
  JSValueWrapper& operator=(const JSArrayType& rhs) noexcept;

 public:
  bool operator==(const JSValueWrapper& rhs) const noexcept;
  bool operator!=(const JSValueWrapper& rhs) const noexcept;
  bool operator<(const JSValueWrapper& rhs) const noexcept;
  bool operator<=(const JSValueWrapper& rhs) const noexcept;
  bool operator>(const JSValueWrapper& rhs) const noexcept;
  bool operator>=(const JSValueWrapper& rhs) const noexcept;

 public:
  inline Type type() noexcept { return type_; }
  inline Type type() const noexcept { return type_; }

 public:
  bool IsUndefined() const noexcept;
  bool IsNull() const noexcept;
  bool IsNullOrUndefined() const noexcept;
  bool IsBoolean() const noexcept;
  bool IsInt32() const noexcept;
  bool IsUInt32() const noexcept;
  bool IsDouble() const noexcept;
  bool IsNumber() const noexcept;
  bool IsString() const noexcept;
  bool IsArray() const noexcept;
  bool IsObject() const noexcept;

 public:
  int32_t Int32Value() const;
  uint32_t UInt32Value() const;
  double DoubleValue() const;
  bool BooleanValue() const;
  std::string& StringValue();
  const std::string& StringValue() const;
  JSObjectType& ObjectValue();
  const JSObjectType& ObjectValue() const;
  JSArrayType& ArrayValue();
  const JSArrayType& ArrayValue() const;

 private:
  inline void deallocate();

 private:
  Type type_ = Type::Undefined;
  union {
    uint32_t uint32_value_;
    int32_t int32_value_;
    double double_value_;
    bool bool_value_;
    std::string string_value_;
    JSObjectType object_value_;
    JSArrayType array_value_;
  };

  friend std::hash<JSValueWrapper>;
};

}  // namespace base
}  // namespace hippy

template <>
struct std::hash<hippy::base::JSValueWrapper> {
  std::size_t operator()(
      const hippy::base::JSValueWrapper& value) const noexcept;

 private:
  const static size_t UndefinedHashValue = 0x79476983;
  const static size_t NullHashValue = 0x7a695478;
};

javascript wrapper函数介绍

在设计javascript的继承体系时,有一个重要需求,方法链。通俗地说,说是在方法中调用父类的同名方法。类似java的this.super().method()。如何把父类的同名方法包装到子类中呢?这就要用到wrapper函数。之所以叫wrapper,而不是wrap,因为它比wrap更加wrapper。比如像Ext那种深度继承的结构中,如果父类没有找祖父,祖父没有找曾祖父,沿着原型链层层上溯,以获取它所需要的功能。此外,wrapper函数在jQuery也有应用,分为三种wrapAll,wrapinner,wrap,专门用来对付IE的table或其他DOM。

例子

 
    var greeting = function(world){
      return "hello " + world +"!";
    };
    alert(greeting("world"));

var greeting = function(world){ return "hello " + world +"!"; }; alert(greeting("world"));

运行代码

我们把它塞进更深一层的作用域,非bind函数。

 
    var wrap= function(fn){
      return function(){
        return fn.apply(null,arguments);
      };
    };

var wrap= function(fn){ return function(){ return fn.apply(null,arguments); }; }; var greeting = function(world){ return "hello " + world +"!"; }; alert(greeting("world")); alert(wrap(greeting)("world"))

运行代码

但这只是延迟了它的执行时间而已。上面函数中的null,也可以换成window。

这样就可以如下神奇效果:

var wrapper= function(fn){ var temp = function(){ return fn.apply(this,arguments); }; temp.wrap = function(callback){ var prev = fn; fn = function(){ return callback.apply(prev,arguments); }; }; return temp; }; var html = function(str){ //原函数数 return ""+str+""; } alert(html("段落")); var p = wrapper(html);//第一次包装 alert(p("段落")) p.wrap(function(str){//第二次包装 return ""+this(str)+"

"; }); alert(p("段落")); p.wrap(function(str){//第三次包装 return ""+this(str)+""; }); alert(p("段落"));

运行代码

可以看出,this总是为原来的同名函数(p),也就是说,我们可以称之为父方法,这样也super关键字或者相关的代替品也不用了,轻松调用原来覆盖了父类的方法。

Logo

智屏生态联盟致力于大屏生态发展,利用大屏快应用技术降低开发者开发、发布大屏应用门槛

更多推荐