详解valueOf() 与toString()是做什么的以及其在各种情况下的应用

前言

各种引用对象都继承或最终继承于 Object ,使用着Object的原型,所以它们不管何时都有 toString() 和 valueOf() 方法,只不过有些类型的原型重写了这两个方法,比如 Function 实例的原型就重写了 toString() 方法,按照原型链的规则,如果方法和属性在原型链的各原型中有重名,则优先使用最近的方法和属性。


先看看常用的引用类型重写了这两个方法的情况

  • Function 重写了 toString()
  • Date 重写了 toString() 也重写了 valueOf()
  • Array 重写了 toString()
阅读更多

Node.js的版本升级

查看本地node版本

node -v

安装n模块

npm install -g n(mac需要在命令的前面加上sudo)

升级到指定的版本/最新版本,升级之前,可以执行n ls(查看可以升级的版本)

n 8.10.1(版本号)
或者你可以安装最新的稳定版本
n stable

4.安装完成以后,检查一下是否升级成功

node -v

JavaScript里的循环方法:forEach,for-in,for-of

JavaScript诞生已经有20多年了,我们一直使用的用来循环一个数组的方法是这样的:

for (var index = 0; index < myArray.length; index++) {
  console.log(myArray[index]);
}

自从JavaScript5起,我们开始可以使用内置的 forEach 方法:

myArray.forEach(function (value) {
  console.log(value);
});

写法简单了许多,但也有短处:你不能中断循环(使用break语句或使用return语句。
JavaScript里还有一种循环方法:for–in。
for-in 循环实际是为循环enumerable对象而设计的:

var obj = {a:1, b:2, c:3};
    
for (var prop in obj) {
  console.log("obj." + prop + " = " + obj[prop]);
}

// 输出:
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"

你也可以用它来循环一个数组:

for (var index in myArray) {    // 不推荐这样
  console.log(myArray[index]);
}

不推荐用for-in来循环一个数组,因为,不像对象,数组的index跟普通的对象属性不一样,是重要的数值序列指标。
总之,for–in是用来循环带有字符串key的对象的方法。

阅读更多

nodejs 搭建本地服务器 展示文件夹

const express = require('express')
const http = require('http')
const app = express()
const port = 80
var serveIndex = require('serve-index')

app.use(express.static('../'))
app.use(serveIndex('../'))

function getIPAdress() {
    let interfaces = require('os').networkInterfaces()
    for (var devName in interfaces) {
        var iface = interfaces[devName]
        for (var i = 0; i < iface.length; i++) {
            let alias = iface[i]
            if (
                alias.family === 'IPv4' &&
                alias.address !== '127.0.0.1' &&
                !alias.internal
            ) {
                // console.log(alias.address);

                return alias.address
            }
        }
    }
}

var server = http.createServer(app)

server.listen(port, () => {
    console.log(`Example app listening at http://${getIPAdress()}:${port}`)
})

你不知道的浏览器渲染原理

在我们面试过程中,面试官经常会问到这么一个问题,那就是从在浏览器地址栏中输入URL到页面显示,浏览器到底发生了什么?这个问题看起来是老生常谈,但是这个问题回答的好坏,确实可以很好的反映出面试者知识的广度和深度。
本文从浏览器角度来告诉你,URL后输入后按回车,浏览器内部究竟发生了什么,读完本文后,你将了解到:

  • 浏览器内有哪些进程,这些进程都有些什么作用

  • 浏览器地址输入URL后,内部的进程、线程都做了哪些事

  • 我们与浏览器交互时,内部进程是怎么处理这些交互事件的

阅读更多

揭开在线协作的神秘面纱 – OT 算法

相信大家或多或少都有使用过在线文档,国内的像我们在做的 腾讯文档 还有其他家的很多类似产品。今天主要为大家揭开在线协作的神秘面纱,那就是 OT 算法。

背景

在线文档,抽象一下,这些产品的模式都是富文本编辑器+后台,富文本编辑器产生内容,展示内容,然后后台负责保存。
富文本编辑器现在业界已经有很多成熟的产品,像 codeMirror ,这一块本身也是很复杂的一块,也不是咱们这次关注的重点方向。
不知道大家平常在用这些产品的时候有没有思考过一个问题,在线文档编辑的时候产生冲突怎么办?

阅读更多

函数柯里化

柯里化 - 维基百科,自由的百科全书
把接受多个参数函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

柯里化有3个常见作用:

  1. 参数复用
  2. 提前确定
  3. 延迟计算/运行

基本实现

var foo = function(a) {
    return function(b) {
        return a * a + b * b;
    }
}

调用上述函数:(foo(3))(4),或直接foo(3)(4)

阅读更多

数组扁平化

Array.prototype.flat()

flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。

const arr1 = [0, 1, 2, [3, 4]];

console.log(arr1.flat());
// expected output: [0, 1, 2, 3, 4]

const arr2 = [0, 1, 2, [[[3, 4]]]];

console.log(arr2.flat(2));
// expected output: [0, 1, 2, [3, 4]]
阅读更多

实时协同编辑的实现

在最近某个项目中打算使用协同编辑来解决冲突问题,因此抽空调研了现有的实现方案,结果发现要想做完美是很难的,但我们可以低成本地做到不错的效果,本文将介绍几种实现方法,大家在项目中如果有需要可以参考。

什么是实时协同编辑

这里所说的实时协同编辑,是指多人同时编辑一个文档,最典型的例子是 Google Docs,你可以实时看到别人做出的修改,不用手动刷新页面。

要实现实时编辑,我们需要解决两个技术点:实时通信问题、编辑冲突问题,其中实时通信问题比较好解决,可以使用 long pull 或 WebSocket,所以这里就不过多讨论了,重点将放在如何解决编辑冲突问题上。

可选方案

接下来将从易至难的顺序来介绍几种可行的方案,分别是:「编辑锁」、「GNU diff-patch」、「Myer’s diff-patch」、「Operational Transformation」和「分布式 Operational Transformation」。

阅读更多

偏函数

偏函数是 [[函数柯里化]] 运算的一种特定应用场景。简单描述,就是把一个函数的某些参数先固化,也就是设置默认值,返回一个新的函数,在新函数中继续接收剩余参数,这样调用这个新函数会更简单。

下面是一个类型检测函数,接收两个参数,第 1 个表示类型字符串,第 2 个表示检测的数据。

var isType = function (type, obj) {  //偏函数
    return Object.prototype.toString.call(obj) == '[object ' + type + ']';
}
阅读更多