Baseline Widely available
ÐбÑÐµÐºÑ Proxy
позволÑÐµÑ ÑоздаÑÑ Ð¿ÑокÑи Ð´Ð»Ñ Ð´ÑÑгого обÑекÑа, Ð¼Ð¾Ð¶ÐµÑ Ð¿ÐµÑеÑ
ваÑÑваÑÑ Ð¸ пеÑеопÑеделиÑÑ Ð¾ÑновнÑе опеÑаÑии Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ обÑекÑа.
ÐÑокÑи иÑполÑзÑÑÑÑÑ Ð¿ÑогÑаммиÑÑами Ð´Ð»Ñ Ð¾Ð±ÑÑÐ²Ð»ÐµÐ½Ð¸Ñ ÑаÑÑиÑенной ÑеманÑики JavaScript обÑекÑов. СÑандаÑÑÐ½Ð°Ñ ÑеманÑика Ñеализована в движке JavaScript, коÑоÑÑй обÑÑно напиÑан на низкоÑÑовневом ÑзÑке пÑогÑаммиÑованиÑ, напÑÐ¸Ð¼ÐµÑ C++. ÐÑокÑи позволÑÑÑ Ð¿ÑогÑаммиÑÑÑ Ð¾Ð¿ÑеделиÑÑ Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ðµ обÑекÑа пÑи помоÑи JavaScript. ÐÑÑгими Ñловами они ÑвлÑÑÑÑÑ Ð¸Ð½ÑÑÑÑменÑом меÑапÑогÑаммиÑованиÑ.
ÐÑимеÑание: ÑеализаÑÐ¸Ñ Ð¿ÑокÑи в SpiderMonkey ÑвлÑеÑÑÑ Ð¿ÑоÑоÑипом, в коÑоÑом пÑокÑи API и ÑеманÑика не ÑÑабилÑнÑ. Также, ÑеализаÑÐ¸Ñ Ð² SpiderMonkey Ð¼Ð¾Ð¶ÐµÑ Ð½Ðµ ÑооÑвеÑÑÑвоваÑÑ Ð¿Ð¾Ñледней веÑÑии ÑпеÑиÑикаÑии. Ðна Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð° в лÑбой Ð¼Ð¾Ð¼ÐµÐ½Ñ Ð¸ пÑедоÑÑавлÑеÑÑÑ Ð¸ÑклÑÑиÑелÑно как ÑкÑпеÑименÑалÑÐ½Ð°Ñ ÑÑнкÑиÑ. Ðе полагайÑеÑÑ Ð½Ð° Ð½ÐµÑ Ð² пÑоизводÑÑвенном коде.
ÐÑа ÑÑÑаниÑа опиÑÑÐ²Ð°ÐµÑ Ð½Ð¾Ð²Ñй API (назÑваемÑй «непоÑÑедÑÑвеннÑм пÑокÑиÑованием»), коÑоÑÑй ÑвлÑеÑÑÑ ÑаÑÑÑÑ Firefox 18. ÐÐ»Ñ Ð¿ÑоÑмоÑÑа ÑÑаÑого API (Firefox 17 и ниже) поÑеÑиÑе ÑÑÑаниÑÑ Ð¾Ð¿Ð¸ÑÐ°Ð½Ð¸Ñ ÑÑаÑого пÑокÑи API.
ТеÑминологиÑÐ¢ÐµÑ Ð½Ð¸ÑеÑкий ÑеÑмин Ð´Ð»Ñ ÑÑой ÑÑнкÑии.
ÐбÑекÑ, обоÑаÑиваÑÑий иÑÑ Ð¾Ð´Ð½Ñй обÑекÑ.
ÐбÑекÑ-замениÑелÑ, ÑодеÑжаÑий ловÑÑки. ÐпÑеделÑеÑ, какие опеÑаÑии бÑдÑÑ Ð¿ÐµÑÐµÑ Ð²Ð°ÑенÑ, Ñакже пеÑеопÑеделÑÐµÑ Ð¿ÐµÑÐµÑ Ð²Ð°ÑеннÑе опеÑаÑии.
ÐеÑодÑ, коÑоÑÑе пÑедоÑÑавлÑÑÑ Ð´Ð¾ÑÑÑп к ÑвойÑÑвам. ÐÑо аналогиÑно конÑепÑии ловÑÑек в опеÑаÑионнÑÑ ÑиÑÑÐµÐ¼Ð°Ñ .
ÐÑÑ Ð¾Ð´Ð½Ñй обÑекÑ, коÑоÑÑй виÑÑÑализиÑÑеÑÑÑ Ð¿ÑокÑи. Ðн ÑаÑÑо иÑполÑзÑеÑÑÑ Ð² каÑеÑÑве иÑÑоÑника даннÑÑ Ð² пÑокÑи. ÐÐ»Ñ Ð½ÐµÐ³Ð¾ пÑовеÑÑÑÑÑÑ Ð¸Ð½Ð²Ð°ÑианÑÑ Ð¾ÑноÑиÑелÑно ÑаÑÑиÑÑемоÑÑи и наÑÑÑаиваемоÑÑи ÑвойÑÑв.
ÐÑокÑи - ÑÑо новÑе обÑекÑÑ; невозможно вÑполниÑÑ "пÑокÑиÑование" ÑÑÑеÑÑвÑÑÑего обÑекÑа. ÐÑÐ¸Ð¼ÐµÑ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¿ÑокÑи:
var p = new Proxy(target, handler);
Ðде:
target
â иÑÑ
однÑй обÑÐµÐºÑ (Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¾Ð±ÑекÑом лÑбого Ñипа, вклÑÑÐ°Ñ Ð¼Ð°ÑÑив, ÑÑнкÑÐ¸Ñ Ð¸ даже дÑÑгой пÑокÑи обÑекÑ).handler
â обÑекÑ-обÑабоÑÑик, меÑÐ¾Ð´Ñ (ловÑÑки) коÑоÑого опÑеделÑÑÑ Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ðµ пÑокÑи во вÑÐµÐ¼Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¾Ð¿ÐµÑаÑии над ним.ÐÑе ловÑÑки опÑионалÑнÑ. Ð ÑлÑÑае, еÑли ловÑÑка не задана, Ñо ÑÑандаÑÑнÑм поведением бÑÐ´ÐµÑ Ð¿ÐµÑенапÑавление опеÑаÑии к обÑекÑÑ-Ñели.
JavaScript-код ÐеÑод обÑабоÑÑика ÐпиÑаниеObject.getOwnPropertyDescriptor(proxy, name)
getOwnPropertyDescriptor function(target, name) -> PropertyDescriptor | undefined
Ðолжен возвÑаÑаÑÑ Ð²ÐµÑнÑй обÑекÑ-опиÑание ÑвойÑÑва или undefined
, ÑÑÐ¾Ð±Ñ Ð¿Ð¾ÐºÐ°Ð·Ð°ÑÑ, ÑÑо ÑвойÑÑво Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ name
ÑÑÑеÑÑвÑÐµÑ Ð² ÑмÑлиÑÑемом обÑекÑе. Object.getOwnPropertyNames(proxy)
Object.getOwnPropertySymbols(proxy)
Object.keys(proxy)
ownKeys function(target) -> [string | symbol]
ÐозвÑаÑÐ°ÐµÑ Ð¼Ð°ÑÑив вÑеÑ
ÑобÑÑвеннÑÑ
(не ÑнаÑледованнÑÑ
) имÑн ÑвойÑÑв ÑмÑлиÑÑемого обÑекÑа. Object.defineProperty(proxy,name,pd)
defineProperty function(target, name, propertyDescriptor) -> any
ÐадаÑÑ Ð½Ð¾Ð²Ð¾Ðµ ÑвойÑÑво, аÑÑибÑÑÑ ÐºÐ¾ÑоÑого опÑеделÑÑÑÑÑ Ð¿ÑедоÑÑавленнÑм propertyDescriptor
. ÐозвÑаÑаемое знаÑение меÑода игноÑиÑÑеÑÑÑ. delete proxy.name
deleteProperty function(target, name) -> boolean
УдалÑÐµÑ Ð¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð½Ð¾Ðµ ÑвойÑÑво из пÑокÑи. ÐозвÑаÑÐ°ÐµÑ true
в ÑлÑÑае ÑÑпеÑного ÑÐ´Ð°Ð»ÐµÐ½Ð¸Ñ ÑвойÑÑва name
. Object.preventExtensions(proxy)
preventExtensions function(target) -> boolean
ÐÐµÐ»Ð°ÐµÑ Ð¾Ð±ÑÐµÐºÑ Ð½ÐµÑаÑÑиÑÑемÑм. ÐозвÑаÑÐ°ÐµÑ true
пÑи ÑÑпеÑном вÑполнении. name in proxy
has function(target, name) -> boolean
proxy.name
(in the context of "getting the value") receiver.name
(if receiver
inherits from a proxy and does not override name
) get function(target, name, receiver) -> any
receiver
â ÑÑо пÑокÑи или обÑекÑ, ÑнаÑледованнÑй Ð¾Ñ Ð¿ÑокÑи. proxy.name = val
(in the context of "setting the value") receiver.name = val
(if receiver
inherits from a proxy and does not override name
) set function(target, name, val, receiver) -> boolean
receiver
â ÑÑо пÑокÑи или обÑекÑ, ÑнаÑледованнÑй Ð¾Ñ Ð¿ÑокÑи. proxy(...args) proxy.apply(thisValue, args) proxy.call(thisValue, ...args)
apply function(target, thisValue, args) -> any
target
должен бÑÑÑ ÑÑнкÑией. new proxy(...args)
construct function(target, args) -> object
target
должен бÑÑÑ ÑÑнкÑией. ÐнваÑианÑÑ
ÐеÑмоÑÑÑ Ð½Ð° Ñо, ÑÑо пÑокÑи пÑедоÑÑавлÑÑÑ Ð¼Ð½Ð¾Ð³Ð¾ возможноÑÑей полÑзоваÑелÑм, некоÑоÑÑе опеÑаÑии не пеÑÐµÑ Ð²Ð°ÑÑваÑÑÑÑ Ð´Ð»Ñ ÑÐ¾Ñ ÑÐ°Ð½ÐµÐ½Ð¸Ñ Ð¿Ð¾ÑÑоÑнÑÑва ÑзÑка:
==
, ===
) не пеÑеÑ
ваÑÑваеÑÑÑ. p1 === p2
ÑавнÑ, ÑолÑко еÑли p1
и p2
ÑÑÑлаÑÑÑÑ Ð½Ð° один и ÑÐ¾Ñ Ð¶Ðµ пÑокÑи.Object.getPrototypeOf(proxy)
вÑегда возвÑаÑÐ°ÐµÑ Object.getPrototypeOf(target)
, поÑÐ¾Ð¼Ñ ÑÑо в ES2015 пеÑеÑ
ваÑÑик getPrototypeOf пока не Ñеализован.typeof proxy
вÑегда возвÑаÑÐ°ÐµÑ typeof target
. Ð ÑаÑÑноÑÑи, proxy
Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¸ÑполÑзован как ÑÑнкÑÐ¸Ñ ÑолÑко еÑли target
ÑвлÑеÑÑÑ ÑÑнкÑией.Array.isArray(proxy)
вÑегда возвÑаÑÐ°ÐµÑ Array.isArray(target)
.Object.prototype.toString.call(proxy)
вÑегда возвÑаÑÐ°ÐµÑ Object.prototype.toString.call(target)
, поÑÐ¾Ð¼Ñ ÑÑо в ES2015 пеÑеÑ
ваÑÑик Symbol.toStringTag пока не Ñеализован.ÐбÑекÑ, возвÑаÑаÑÑий знаÑение 37
, в ÑлÑÑае оÑÑÑÑÑÑÐ²Ð¸Ñ ÑвойÑÑва Ñ ÑказаннÑм именем:
var handler = {
get: function (target, name) {
return name in target ? target[name] : 37;
},
};
var p = new Proxy({}, handler);
p.a = 1;
p.b = undefined;
console.log(p.a, p.b); // 1, undefined
console.log("c" in p, p.c); // false, 37
ÐеÑенапÑавлÑÑÑий пÑокÑи
Рданном пÑимеÑе Ð¼Ñ Ð¸ÑполÑзÑем JavaScript обÑекÑ, к коÑоÑÐ¾Ð¼Ñ Ð½Ð°Ñ Ð¿ÑокÑи напÑавлÑÐµÑ Ð²Ñе запÑоÑÑ:
var target = {};
var p = new Proxy(target, {});
p.a = 37; // опеÑаÑÐ¸Ñ Ð¿ÐµÑенапÑавлена пÑокÑи
console.log(target.a); // 37. ÐпеÑаÑÐ¸Ñ Ð±Ñла ÑÑпеÑно пеÑенапÑавлена
ÐÑовеÑка
ÐÑи помоÑи Proxy
Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе легко пÑовеÑÑÑÑ Ð¿ÐµÑедаваемÑе обÑекÑÑ Ð·Ð½Ð°ÑениÑ:
let validator = {
set: function (obj, prop, value) {
if (prop === "age") {
if (!Number.isInteger(value)) {
throw new TypeError("The age is not an integer");
}
if (value > 200) {
throw new RangeError("The age seems invalid");
}
}
// СÑандаÑÑное ÑоÑ
Ñанение знаÑениÑ
obj[prop] = value;
// ÐбознаÑиÑÑ ÑÑпеÑ
return true;
},
};
let person = new Proxy({}, validator);
person.age = 100;
console.log(person.age); // 100
person.age = "young"; // ÐÑÐ·Ð¾Ð²ÐµÑ Ð¸ÑклÑÑение
person.age = 300; // ÐÑÐ·Ð¾Ð²ÐµÑ Ð¸ÑклÑÑение
Ðополнение конÑÑÑÑкÑоÑа
ФÑнкÑÐ¸Ñ Ð¿ÑокÑи Ð¼Ð¾Ð¶ÐµÑ Ð»ÐµÐ³ÐºÐ¾ дополниÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑÐ¾Ñ Ð½Ð¾Ð²Ñм:
function extend(sup, base) {
var descriptor = Object.getOwnPropertyDescriptor(
base.prototype,
"constructor",
);
const prototype = { ...base.prototype };
base.prototype = Object.create(sup.prototype);
base.prototype = Object.assign(base.prototype, prototype);
var handler = {
construct: function (target, args) {
var obj = Object.create(base.prototype);
this.apply(target, obj, args);
return obj;
},
apply: function (target, that, args) {
sup.apply(that, args);
base.apply(that, args);
},
};
var proxy = new Proxy(base, handler);
descriptor.value = proxy;
Object.defineProperty(base.prototype, "constructor", descriptor);
return proxy;
}
var Person = function (name) {
this.name = name;
};
var Boy = extend(Person, function (name, age) {
this.age = age;
});
Boy.prototype.sex = "M";
var Peter = new Boy("Peter", 13);
console.log(Peter.sex); // "M"
console.log(Peter.name); // "Peter"
console.log(Peter.age); // 13
ÐанипÑлÑÑÐ¸Ñ DOM ÑлеменÑами
Ðногда Ð²Ð¾Ð·Ð½Ð¸ÐºÐ°ÐµÑ Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ÑÑÑ Ð¿ÐµÑеклÑÑиÑÑ Ð°ÑÑибÑÑ Ð¸Ð»Ð¸ Ð¸Ð¼Ñ ÐºÐ»Ð°ÑÑа Ñ Ð´Ð²ÑÑ ÑазнÑÑ ÑлеменÑов:
let view = new Proxy(
{
selected: null,
},
{
set: function (obj, prop, newval) {
let oldval = obj[prop];
if (prop === "selected") {
if (oldval) {
oldval.setAttribute("aria-selected", "false");
}
if (newval) {
newval.setAttribute("aria-selected", "true");
}
}
// СÑандаÑÑное ÑоÑ
Ñанение знаÑениÑ
obj[prop] = newval;
},
},
);
let i1 = (view.selected = document.getElementById("item-1"));
console.log(i1.getAttribute("aria-selected")); // 'true'
let i2 = (view.selected = document.getElementById("item-2"));
console.log(i1.getAttribute("aria-selected")); // 'false'
console.log(i2.getAttribute("aria-selected")); // 'true'
Ðзменение знаÑений и дополниÑелÑнÑе ÑвойÑÑва
ÐÑокÑи обÑÐµÐºÑ products
пÑовеÑÑÐµÑ Ð¿ÐµÑедаваемÑе знаÑÐµÐ½Ð¸Ñ Ð¸ пÑеобÑазÑÐµÑ Ð¸Ñ
в маÑÑив в ÑлÑÑае необÑ
одимоÑÑи. ÐбÑÐµÐºÑ Ñакже поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑное ÑвойÑÑво latestBrowser
на ÑÑение и запиÑÑ.
let products = new Proxy(
{
browsers: ["Internet Explorer", "Netscape"],
},
{
get: function (obj, prop) {
// ÐополниÑелÑное ÑвойÑÑво
if (prop === "latestBrowser") {
return obj.browsers[obj.browsers.length - 1];
}
// СÑандаÑÑнÑй возвÑÐ°Ñ Ð·Ð½Ð°ÑениÑ
return obj[prop];
},
set: function (obj, prop, value) {
// ÐополниÑелÑное ÑвойÑÑво
if (prop === "latestBrowser") {
obj.browsers.push(value);
return;
}
// ÐÑеобÑазование знаÑениÑ, еÑли оно не маÑÑив
if (typeof value === "string") {
value = [value];
}
// СÑандаÑÑное ÑоÑ
Ñанение знаÑениÑ
obj[prop] = value;
},
},
);
console.log(products.browsers); // ['Internet Explorer', 'Netscape']
products.browsers = "Firefox"; // пеÑедаÑÑÑÑ ÐºÐ°Ðº ÑÑÑока (по оÑибке)
console.log(products.browsers); // ['Firefox'] <- пÑоблем неÑ, знаÑение - маÑÑив
products.latestBrowser = "Chrome";
console.log(products.browsers); // ['Firefox', 'Chrome']
console.log(products.latestBrowser); // 'Chrome'
ÐоиÑк ÑлеменÑа маÑÑива по его ÑвойÑÑвÑ
ÐаннÑй пÑокÑи ÑаÑÑиÑÑÐµÑ Ð¼Ð°ÑÑив дополниÑелÑнÑми возможноÑÑÑми. Ðак Ð²Ñ Ð²Ð¸Ð´Ð¸Ñе, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе гибко "задаваÑÑ" ÑвойÑÑва без иÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Object.defineProperties
. ÐаннÑй пÑÐ¸Ð¼ÐµÑ Ñакже Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¸ÑполÑзован Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка ÑÑÑоки ÑаблиÑÑ Ð¿Ð¾ ÐµÑ ÑÑейке. Ð ÑÑом ÑлÑÑае ÑелÑÑ Ð±ÑÐ´ÐµÑ table.rows
.
let products = new Proxy(
[
{ name: "Firefox", type: "browser" },
{ name: "SeaMonkey", type: "browser" },
{ name: "Thunderbird", type: "mailer" },
],
{
get: function (obj, prop) {
// СÑандаÑÑное возвÑаÑение знаÑениÑ; prop обÑÑно ÑвлÑеÑÑÑ ÑиÑлом
if (prop in obj) {
return obj[prop];
}
// ÐолÑÑение колиÑеÑÑва пÑодÑкÑов; пÑевдоним products.length
if (prop === "number") {
return obj.length;
}
let result,
types = {};
for (let product of obj) {
if (product.name === prop) {
result = product;
}
if (types[product.type]) {
types[product.type].push(product);
} else {
types[product.type] = [product];
}
}
// ÐолÑÑение пÑодÑкÑа по имени
if (result) {
return result;
}
// ÐолÑÑение пÑодÑкÑов по ÑипÑ
if (prop in types) {
return types[prop];
}
// ÐолÑÑение Ñипов пÑодÑкÑов
if (prop === "types") {
return Object.keys(types);
}
return undefined;
},
},
);
console.log(products[0]); // { name: 'Firefox', type: 'browser' }
console.log(products["Firefox"]); // { name: 'Firefox', type: 'browser' }
console.log(products["Chrome"]); // undefined
console.log(products.browser); // [{ name: 'Firefox', type: 'browser' }, { name: 'SeaMonkey', type: 'browser' }]
console.log(products.types); // ['browser', 'mailer']
console.log(products.number); // 3
ÐÑÐ¸Ð¼ÐµÑ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²ÑеÑ
пеÑеÑ
ваÑÑиков
Рданном пÑимеÑе, иÑполÑзÑÑÑем вÑе Ð²Ð¸Ð´Ñ Ð¿ÐµÑеÑ
ваÑÑиков, Ð¼Ñ Ð¿Ð¾Ð¿ÑÑаемÑÑ Ð¿ÑокÑиÑоваÑÑ Ð½Ðµ наÑивнÑй обÑекÑ, коÑоÑÑй ÑаÑÑиÑно пÑиÑпоÑоблен Ð´Ð»Ñ ÑÑого - docCookies,
Ñозданном в Ñазделе "little framework" и опÑбликованном на ÑÑÑаниÑе document.cookie
.
/*
var docCookies = ... полÑÑиÑÑ Ð¾Ð±ÑÐµÐºÑ "docCookies" можно здеÑÑ:
https://developer.mozilla.org/ru/docs/DOM/document.cookie#A_little_framework.3A_a_complete_cookies_reader.2Fwriter_with_full_unicode_support
*/
var docCookies = new Proxy(docCookies, {
get: function (oTarget, sKey) {
return oTarget[sKey] || oTarget.getItem(sKey) || undefined;
},
set: function (oTarget, sKey, vValue) {
if (sKey in oTarget) {
return false;
}
return oTarget.setItem(sKey, vValue);
},
deleteProperty: function (oTarget, sKey) {
if (sKey in oTarget) {
return false;
}
return oTarget.removeItem(sKey);
},
enumerate: function (oTarget, sKey) {
return oTarget.keys();
},
iterate: function (oTarget, sKey) {
return oTarget.keys();
},
ownKeys: function (oTarget, sKey) {
return oTarget.keys();
},
has: function (oTarget, sKey) {
return sKey in oTarget || oTarget.hasItem(sKey);
},
hasOwn: function (oTarget, sKey) {
return oTarget.hasItem(sKey);
},
defineProperty: function (oTarget, sKey, oDesc) {
if (oDesc && "value" in oDesc) {
oTarget.setItem(sKey, oDesc.value);
}
return oTarget;
},
getPropertyNames: function (oTarget) {
return Object.getPropertyNames(oTarget).concat(oTarget.keys());
},
getOwnPropertyNames: function (oTarget) {
return Object.getOwnPropertyNames(oTarget).concat(oTarget.keys());
},
getPropertyDescriptor: function (oTarget, sKey) {
var vValue = oTarget[sKey] || oTarget.getItem(sKey);
return vValue
? {
value: vValue,
writable: true,
enumerable: true,
configurable: false,
}
: undefined;
},
getOwnPropertyDescriptor: function (oTarget, sKey) {
var vValue = oTarget.getItem(sKey);
return vValue
? {
value: vValue,
writable: true,
enumerable: true,
configurable: false,
}
: undefined;
},
fix: function (oTarget) {
return "not implemented yet!";
},
});
/* ÐÑовеÑка cookies */
alert((docCookies.my_cookie1 = "First value"));
alert(docCookies.getItem("my_cookie1"));
docCookies.setItem("my_cookie1", "Changed value");
alert(docCookies.my_cookie1);
СмоÑÑиÑе Ñакже ÐиÑензионнÑе пÑимеÑаниÑ
ÐекоÑоÑое ÑодеÑжимое (ÑекÑÑ, пÑимеÑÑ) данной ÑÑÑаниÑÑ Ð±Ñло ÑкопиÑовано или адапÑиÑовано Ñо ÑÑÑÐ°Ð½Ð¸Ñ Ð²Ð¸ÐºÐ¸ ECMAScript, имеÑÑей лиÑÐµÐ½Ð·Ð¸Ñ CC 2.0 BY-NC-SA
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4