微信公众号:从国企到阿里的面试经历(一)

首先,跟大家说声抱歉,年后实在是太忙,一不小心就断更了 4 个月。从今天开始,我尽量坚持月更,分享最干的干货给大家。第一篇,从国企到阿里的面试经历(一)。

阅读更多

《JavaScript 闯关记》之垃圾回收和内存管理

垃圾回收和内存管理

JavaScript 具有自动垃圾收集机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存。而在 C 和 C++ 之类的语言中,开发人员的一项基本任务就是手工跟踪内存的使用情况,这是造成许多问题的一个根源。

在编写 JavaScript 程序时,开发人员不用再关心内存使用问题,所需内存的分配以及无用内存的回收完全实现了自动管理。这种垃圾收集机制的原理其实很简单:找出那些不再继续使用的变量,然后释放其占用的内存。为此,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间),周期性地执行这一操作。

正因为垃圾回收器的存在,许多人认为 JavaScript 不用太关心内存管理的问题,但如果不了解 JavaScript 的内存管理机制,我们同样非常容易成内存泄漏(内存无法被回收)的情况。

阅读更多

《JavaScript 闯关记》之原型及原型链

原型链是一种机制,指的是 JavaScript 每个对象都有一个内置的 __proto__ 属性指向创建它的构造函数的 prototype(原型)属性。原型链的作用是为了实现对象的继承,要理解原型链,需要先从函数对象constructornewprototype__proto__ 这五个概念入手。

函数对象

前面讲过,在 JavaScript 里,函数即对象,程序可以随意操控它们。比如,可以把函数赋值给变量,或者作为参数传递给其他函数,也可以给它们设置属性,甚至调用它们的方法。下面示例代码对「普通对象」和「函数对象」进行了区分。

普通对象:

1
2
var o1 = {};
var o2 = new Object();

函数对象:

1
2
3
function f1(){};
var f2 = function(){};
var f3 = new Function('str','console.log(str)');

简单的说,凡是使用 function 关键字或 Function 构造函数创建的对象都是函数对象。而且,只有函数对象才拥有 prototype (原型)属性。

constructor 构造函数

函数还有一种用法,就是把它作为构造函数使用。像 ObjectArray 这样的原生构造函数,在运行时会自动出现在执行环境中。此外,也可以创建自定义的构造函数,从而自定义对象类型的属性和方法。如下代码所示:

1
2
3
4
5
6
7
8
9
10
11
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
console.log(this.name);
};
}
var person1 = new Person("Stone", 28, "Software Engineer");
var person2 = new Person("Sophie", 29, "English Teacher");

在这个例子中,我们创建了一个自定义构造函数 Person(),并通过该构造函数创建了两个普通对象 person1person2,这两个普通对象均包含3个属性和1个方法。

你应该注意到函数名 Person 使用的是大写字母 P。按照惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头。这个做法借鉴自其他面向对象语言,主要是为了区别于 JavaScript 中的其他函数;因为构造函数本身也是函数,只不过可以用来创建对象而已。

阅读更多

《JavaScript 闯关记》之作用域和闭包

作用域和闭包是 JavaScript 最重要的概念之一,想要进一步学习 JavaScript,就必须理解 JavaScript 作用域和闭包的工作原理。

作用域

任何程序设计语言都有作用域的概念,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在 JavaScript 中,变量的作用域有全局作用域和局部作用域两种。

全局作用域(Global Scope)

在代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下三种情形拥有全局作用域:

1.最外层函数和在最外层函数外面定义的变量拥有全局作用域,例如:

1
2
3
4
5
6
7
8
var global = "global"; // 显式声明一个全局变量
function checkscope() {
var local = "local"; // 显式声明一个局部变量
return global; // 返回全局变量的值
}
console.log(global); // "global"
console.log(checkscope()); // "global"
console.log(local); // error: local is not defined.

上面代码中,global 是全局变量,不管是在 checkscope() 函数内部还是外部,都能访问到全局变量 global

2.所有末定义直接赋值的变量自动声明为拥有全局作用域,例如:

1
2
3
4
5
6
function checkscope() {
var local = "local"; // 显式声明一个局部变量
global = "global"; // 隐式声明一个全局变量(不好的写法)
}
console.log(global); // "global"
console.log(local); // error: local is not defined.

上面代码中,变量 global 未用 var 关键字定义就直接赋值,所以隐式的创建了全局变量 global,但这种写法容易造成误解,应尽量避免这种写法。

3.所有 window 对象的属性拥有全局作用域

一般情况下,window 对象的内置属性都拥有全局作用域,例如 window.namewindow.locationwindow.top 等等。

阅读更多

如何排版 微信公众号「代码块」之 MarkEditor

前段时间写过一篇文章 如何排版微信公众号「代码块」,讲的是如何使用浏览器插件 Markdown Here 来排版代码块。虽然用 Markdown Here 排版出来的样式还不错,但存在一个问题,就是代码之间的换行会全部丢失,需要手动进行调整。如果文章中代码较多的话,调整起来还是挺费劲的。

而我近期写的文章,常常会罗列大量代码,导致每次在公众号发文,都要花1个多小时来调整样式,真是难受想哭。

双11期间,看到 池建强老师 公众号 MacTalk 的文章 如何优雅的购买 Mac 软件。不出我意料,他果然推荐了一家专卖正版 Mac 软件的淘宝店铺 数码荔枝。秉承「老池推荐必精品」的原则,我如愿的淘到了微信公众号排版神器 MarkEditor。当时,该软件有着「双11特惠」和「老池特惠」双重加持,我仅用了 76.5 就拿下了官网售价 128 的 Pro 版本(得意的笑)。

阅读更多