var http = require("http"); var socket = require("socket.io");
// 启http服务 var server = http.createServer(function (req, res) { res.writeHead(200, { "Content-type": "text/html", }); res.end(); });
server.listen("8080"); console.log("Server is running at port 8080...");
// 监听socket连接 socket.listen(server).on("connection", function (client) { // 接收信息 client.on("message", function (msg) { client.send("hello:" + msg); console.log("data from client: ---> " + msg); });
// 断开处理 client.on("disconnect", function () { console.log("Client socket has closed."); }); });
标签
iframe
HTML 内联框架元素<iframe> 表示嵌套的 browsing context。它能够将另一个 HTML 页面嵌入到当前页面中。
1 2 3 4 5 6 7 8
<iframe src="https://mdn-samples.mozilla.org/snippets/html/iframe-simple-contents.html" title="iframe example 1" width="400" height="300" > <p>Your browser does not support iframes.</p> </iframe>
ws.onclose = function (evt) { console.log("Connection closed."); };
WebSocket 客户端 API
WebSocket 构造函数
1
ws = newWebSocket("ws://localhost:8080");
执行上面语句之后,客户端就会与服务器进行连接。
WebSocket.readyState
readyState 属性返回实例对象的当前状态,共用四种.
CONNECTING: 值为 0,表示正在连接.
OPEN: 值为 1,表示连接成功,可以通信.
CLOSEING: 值为 2,表示正在关闭.
CLOSED: 值为 3,表示连接已经关闭,或者打开失败.
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
switch (ws.readyState) { caseWebSocket.CONNECTING: // do something break; caseWebSocket.OPEN: // do something break; caseWebSocket.CLOSING: // do something break; caseWebSocket.CLOSED: // do something break; default: // this never happens break; }
WebSocket.onopen
实例对象的onopen属性,用于指定连接成功后的回调函数.
1 2 3
ws.onopen = function () { ws.send("hello"); };
如果指定多个函数,可以使用addEventListener方法.
1 2 3
ws.addEventListener("open", function (event) { ws.send("hello"); });
原文地址:WTF is this - Understanding the this keyword, call, apply, and bind in JavaScript
原文作者:Tyler McGinnis
译文出自:掘金翻译计划
本文永久链接:github.com/xitu/gold-m…
译者:CoolRice
校对者:周家未
在深入了解 JavaScript 中的 this 关键字之前,有必要先退一步,看一下为什么 this 关键字很重要。this 允许复用函数时使用不同的上下文。换句话说,“this” 关键字允许在调用函数或方法时决定哪个对象应该是焦点。 之后讨论的所有东西都是基于这个理念。我们希望能够在不同的上下文或在不同的对象中复用函数或方法。
我们要关注的第一件事是如何判断 this 关键字的引用。当你试图回答这个问题时,你需要问自己的第一个也是最重要的问题是“这个函数在哪里被调用?”。判断 this 引用什么的 唯一 方法就是看使用 this 关键字的这个方法在哪里被调用的。
const user = { name: "Tyler", age: 27, greet() { alert(`Hello, my name is ${this.name}`); }, mother: { name: "Stacey", greet() { alert(`Hello, my name is ${this.name}`); }, }, };
现在问题变成下面的每个函数调用会警告什么?
1 2
user.greet(); user.mother.greet();
每当判断 this 的引用时,我们都需要查看调用过程,并确认“点的左侧”是什么。第一个调用,user 在点左侧意味着 this 将引用 user。第二次调用中,mother 在点的左侧意味着 this 引用 mother。
如前所述,大约有 80% 的情况下在“点的左侧”都会有一个对象。这就是为什么在判断 this 指向时“查看点的左侧”是你要做的第一件事。但是,如果没有点呢?这就为我们引出了下一条规则
显式绑定
如果 greet 函数不是 user 对象的函数,只是一个独立的函数。
1 2 3 4 5 6 7 8
functiongreet() { alert(`Hello, my name is ${this.name}`); }
const user = { name: "Tyler", age: 27, };
我们知道为了判断 this 的引用我们首先必须查看这个函数的调用位置。现在就引出了一个问题,我们怎样能让 greet 方法调用的时候将 this 指向 user 对象?。我们不能再像之前那样简单的使用 user.greet(),因为 user 并没有 greet 方法。在 JavaScript 中,每个函数都包含了一个能让你恰好解决这个问题的方法,这个方法的名字叫做 call。
functiongreet(lang1, lang2, lang3) { alert( `Hello, my name is ${this.name} and I know ${lang1}, ${lang2}, and ${lang3}` ); }
const user = { name: "Tyler", age: 27, };
const languages = ["JavaScript", "Ruby", "Python"];
const newFn = greet.bind(user, languages[0], languages[1], languages[2]); newFn(); // alerts "Hello, my name is Tyler and I know JavaScript, Ruby, and Python"
new 绑定
第三条判断 this 引用的规则是 new 绑定。若你不熟悉 JavaScript 中的 new 关键字,其实每当用 new 调用函数时,JavaScript 解释器都会在底层创建一个全新的对象并把这个对象当做 this。如果用 new 调用一个函数,this 会自然地引用解释器创建的新对象。
1 2 3 4 5 6 7 8 9 10 11
functionUser(name, age) { /* JavaScript 会在底层创建一个新对象 `this`,它会代理不在 User 原型链上的属性。 如果一个函数用 new 关键字调用,this 就会指向解释器创建的新对象。 */
this.name = name; this.age = age; }
const me = newUser("Tyler", 27);
window 绑定
假如我们有下面这段代码
1 2 3 4 5 6 7 8
functionsayAge() { console.log(`My age is ${this.age}`); }
const user = { name: "Tyler", age: 27, };
如前所述,如果你想用 user 做上下文调用 sayAge,你可以使用 .call、.apply 或 .bind。但如果我们没有用这些方法,而是直接和平时一样直接调用 sayAge 会发生什么呢?
1
sayAge(); // My age is undefined
不出意外,你会得到 My name is undefined,因为 this.age 是 undefined。事情开始变得神奇了。实际上这是因为点的左侧没有任何东西,我们也没有用 .call、.apply、.bind 或者 new 关键字,JavaScript 会默认 this 指向 window 对象。这意味着如果我们向 window 对象添加 age 属性并再次调用 sayAge 方法,this.age 将不再是 undefined 并且变成 window 对象的 age 属性值。不相信?让我们运行这段代码
1 2 3 4 5
window.age = 27;
functionsayAge() { console.log(`My age is ${this.age}`); }
let cat = newCat("米粒", "5个月"); let run = cat.run; let jump = cat.jump; let go = Cat.go; let walk = cat.walk; let drink = cat.drink;
run(); // run undefined jump(); // jump Cat {name: "米粒", jump: ƒ} Cat.go(); // go class Cat {} go(); // go undefined cat.walk(); // walk Window walk(); // walk Window cat.drink(); // drink Cat {name: "米粒", jump: ƒ, drink: ƒ} drink(); // drink Cat {name: "米粒", jump: ƒ, drink: ƒ}
先看 run 方法:当把实例中的方法赋值给一个变量,但是只是赋予了方法的引用,所以当变量在执行方法的时候,其实改变了方法的执行时的上下文。原来执行的上下文是实例 cat,后来赋值之后再执行,上下文就变成了全局,this 默认绑定。class 中使用的是严格模式,在该模式下,全局的 this 默认绑定的是 undefined,不是在严格模式下的时候,若在浏览器中执行,则 this 默认绑定 window。
let [a, b = 2] = [3] a // 3 b // 2,因为b没有对应值,所以是undefined,使用默认值
let [a, b = 2] = [3, 4] a //3 b //4 数组对应对值有没有?如果没有(数组对没有指undefined)就使用默认值,如果有就使用对应值
let [a=2, b=3] = [undefined, null] a //2 b //null let [a=1, b=a] = [2] a //2 b //2,因为b没有对应值,所以是undefined,使用默认值,此时a的默认值为2
对象的解构赋值
前置知识
1 2 3 4 5 6 7 8 9 10 11 12 13 14
let [name, age] = ["hunger", 3]; let p1 = { name, age }; //等同于 let p2 = { name: name, age: age }; 解构范例;
let { name, age } = { name: "jirengu", age: 4 }; name; //‘jirengu’ age; //4 以上代码等同于;
let name; let age; ({ name: name, age: age } = { name: "jirengu", age: 4 });
默认值
1 2 3
let { x, y = 5 } = { x: 1 }; x; //1 y; //5
函数解构
1 2 3 4 5 6 7 8 9 10 11
functionadd([x = 1, y = 2]) { return x + y; } add(); //Error add([2]); //4 add([3, 4]); //7
functionsum({ x, y } = { x: 0, y: 0 }, { a = 1, b = 1 }) { return [x + a, y + b]; } sum({ x: 1, y: 2 }, { a: 2 }); //[3, 3]
作用
1 2 3 4 5 6 7
let [x, y] = [1, 2]; [x, y] = [y, x] x //2 y // 1 functionajax({url, type=‘GET’}){ } ajax({url: ‘http://localhost:3000/getData’})
字符串,数组,对象
字符串
多行字符串
1 2 3 4 5
let str = ` Hi, This is jirengu.com. You can study frontend here. `;
字符串模板
1 2 3 4 5 6 7
let website = "jirengucom"; let who = "You"; let str = `Hi This is ${website}. ${who} can study frontend here `; //${},可以替换变量
1 2 3 4 5
var data = [1, 2, 3, 4]; var liArr = data.map((v) =>`<li>${v}</li>`).join(""); var html = `<ul>${liArr}</ul>`; console.log(html); //"<ul><li>1</li><li>2</li><li>3</li><li>4</li></ul>"
数组
扩展运算符...
主要作用是将数组或对象进行展开.
对象中的扩展运算符(…)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中
1 2 3 4 5 6 7
var a = [1, 2]; console.log(...a); // 1, 2,这三个点相当于脱壳,把数组的壳拿掉 var b = [...a, 3]; b; // [1, 2, 3]
var c = b.concat([4, 5]); //b拼接[4,5]变成[1,2,3,4,5] var d = [...b, 4, 5]; //直接把脱壳后的1,2,3放入数组中
TaiChi is a framework that can use Xposed modules. Modules can change the behavior of systems and applications through it. TaiChi App can run without needing to root, unlock the bootloader; and it supports Android 5.0 ~ 10.
In simple terms, TaiChi is an Xposed-like framework, which can load Xposed modules, modify the system and APP, intercept methods, and execute hook logic.
Relationship with Xposed
TaiChi is an Xposed-like framework, but it has nothing to do with Xposed itself. The only thing that might be related is that TaiChi is compatible with the Xposed modules. Besides, the two are completely different in design thinking, implementation mechanism, and operation logic.
Here are some unique features of TaiChi:
How to use TaiChi?
TaiChi has two working modes: non-root mode and magisk mode. If you don’t want to unlock the bootloader/flash system images, the non-root mode is perfect for you, if you want more control over the system, you can try magisk mode.
What is the difference between non-root mode and magisk mode?
The only different support is that the magisk mode can modify the system, so it can support more modules; such as Greenify / CorePatch, etc. However, Magisk mode requires unlocking the bootloader and installing Magisk, while non-root mode only requires installing a simple APP (TaiChi).
Non-Root mode
Magisk mode
Although the Non-Root mode of TaiChi does not require unlocking the bootloader and is extremely convenient to use, it has some disadvantages, such as the inability to modify the system and the need to uninstall the original APP. Therefore,Magisk module of TaiChi, which can give TaiChi more powerful functions through Magisk; thus breaking through the limitations of the Non-Root mode.
After you flash in the Magisk Module provided by TaiChi, the TaiChi APP will automatically switch from Non-Root mode to Magisk mode: TaiChi APP + TaiChi Magisk Module = TaiChi Magisk. When Magisk Module of TaiChi is disabled or uninstalled, TaiChi will automatically return to Non-Root mode.
If you want to use magisk mode, please download the latest Magisk Module.