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关键字或者相关的代替品也不用了,轻松调用原来覆盖了父类的方法。