整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Top 26 JavaScript面试问题和答案

Top 26 JavaScript面试问题和答案

据Stack Overflow的2018年度调查,JavaScript连续六年成为最常用的编程语言。所以我们必须面对这样的现实,JavaScript已经成为全栈开发技能的基石,在全栈开发面试中都会不可避免地涉及到与JavaScript有关的问题。

FullStack.Cafe汇编了最常见的JavaScript面试问题和答案,希望能够帮助读者找到下一份梦想中的工作。

编程工程概念

Q1:JavaScript中的强制转型(coercion)是指什么?

难度:0

在JavaScript中,两种不同的内置类型间的转换被称为强制转型。强制转型在JavaScript中有两种形式:显式和隐式。

这是一个显式强制转型的例子:

var a="42";
var b=Number( a );
a; // "42"
b; // 42 -- 是个数字!

这是一个隐式强制转型的例子:

var a="42";
var b=a * 1; // "42" 隐式转型成 42 
a; // "42"
b; // 42 -- 是个数字!

Q2:JavaScript中的作用域(scope)是指什么?

难度:?

在JavaScript中,每个函数都有自己的作用域。作用域基本上是变量以及如何通过名称访问这些变量的规则的集合。只有函数中的代码才能访问函数作用域内的变量。

同一个作用域中的变量名必须是唯一的。一个作用域可以嵌套在另一个作用域内。如果一个作用域嵌套在另一个作用域内,最内部作用域内的代码可以访问另一个作用域的变量。


Q3:解释JavaScript中的相等性

难度:?

JavaScript中有严格比较和类型转换比较:

  • 严格比较(例如===)在不允许强制转型的情况下检查两个值是否相等
  • 抽象比较(例如==)在允许强制转型的情况下检查两个值是否相等
var a="42";
var b=42;
a==b; // true
a===b; // false

一些简单的规则:

  • 如果被比较的任何一个值可能是true或false,要用===,而不是==。
  • 如果被比较的任何一个值是这些特定值(0、“”或[]),要用===,而不是==。
  • 在其他情况下,可以安全地使用==。它不仅安全,而且在很多情况下,它可以简化代码,并且提升代码可读性。

Q4:解释什么是回调函数,并提供一个简单的例子。

难度:??

回调函数是可以作为参数传递给另一个函数的函数,并在某些操作完成后执行。下面是一个简单的回调函数示例,这个函数在某些操作完成后打印消息到控制台。

function modifyArray(arr, callback) {
 // 对arr做一些操作
 arr.push(100);
 // 执行传进来的callback函数
 callback();
}
var arr=[1, 2, 3, 4, 5];
modifyArray(arr, function() {
 console.log("array has been modified", arr);
});

Q5:“use strict”的作用是什么?

难度:??

use strict出现在JavaScript代码的顶部或函数的顶部,可以帮助你写出更安全的JavaScript代码。如果你错误地创建了全局变量,它会通过抛出错误的方式来警告你。例如,以下程序将抛出错误:

function doSomething(val) {
 "use strict"; 
 x=val + 10;
}

它会抛出一个错误,因为x没有被定义,并使用了全局作用域中的某个值对其进行赋值,而use strict不允许这样做。下面的小改动修复了这个错误:

function doSomething(val) {
 "use strict"; 
 var x=val + 10;
}

Q6:解释JavaScript中的null和undefined

难度:??

JavaScript中有两种底层类型:null和undefined。它们代表了不同的含义:

  • 尚未初始化的东西:undefined。
  • 目前不可用的东西:null。

Q7:编写一个可以执行如下操作的函数。

难度:??

var addSix=createBase(6);
addSix(10); // 返回16
addSix(21); // 返回27

可以创建一个闭包来存放传递给函数createBase的值。被返回的内部函数是在外部函数中创建的,内部函数就成了一个闭包,它可以访问外部函数中的变量,在本例中是变量baseNumber。

function createBase(baseNumber) {
 return function(N) {
 // 我们在这里访问baseNumber,即使它是在这个函数之外声明的。
 // JavaScript中的闭包允许我们这么做。
 return baseNumber + N;
 }
}
var addSix=createBase(6);
addSix(10);
addSix(21);

Q8:解释JavaScript中的值和类型

难度:??

JavaScript有类型值,但没有类型变量。JavaScript提供了以下几种内置类型:

  • string
  • number
  • boolean
  • null 和 undefined
  • object
  • symbol (ES6中新增的)

Q9:解释事件冒泡以及如何阻止它

难度:??

事件冒泡是指嵌套最深的元素触发一个事件,然后这个事件顺着嵌套顺序在父元素上触发。

防止事件冒泡的一种方法是使用event.cancelBubble或event.stopPropagation()(低于IE 9)。


Q10:JavaScript中的let关键字有什么用?

难度:??

除了可以在函数级别声明变量之外,ES6还允许你使用let关键字在代码块({..})中声明变量。


Q11:如何检查一个数字是否为整数?

难度:??

检查一个数字是小数还是整数,可以使用一种非常简单的方法,就是将它对1进行取模,看看是否有余数。

function isInt(num) {
 return num % 1===0;
}
console.log(isInt(4)); // true
console.log(isInt(12.2)); // false
console.log(isInt(0.3)); // false

Q12:什么是IIFE(立即调用函数表达式)?

难度:???

它是立即调用函数表达式(Immediately-Invoked Function Expression),简称IIFE。函数被创建后立即被执行:

(function IIFE(){
 console.log( "Hello!" );
})();
// "Hello!"

在避免污染全局命名空间时经常使用这种模式,因为IIFE(与任何其他正常函数一样)内部的所有变量在其作用域之外都是不可见的。


Q13:如何在JavaScript中比较两个对象?

难度:???

对于两个非原始值,比如两个对象(包括函数和数组),==和===比较都只是检查它们的引用是否匹配,并不会检查实际引用的内容。

例如,默认情况下,数组将被强制转型成字符串,并使用逗号将数组的所有元素连接起来。所以,两个具有相同内容的数组进行==比较时不会相等:

var a=[1,2,3];
var b=[1,2,3];
var c="1,2,3";
a==c; // true
b==c; // true
a==b; // false

对于对象的深度比较,可以使用deep-equal这个库,或者自己实现递归比较算法。


Q14:你能解释一下ES5和ES6之间的区别吗?

难度:???

  • ECMAScript 5(ES5):ECMAScript的第5版,于2009年标准化。这个标准已在所有现代浏览器中完全实现。
  • ECMAScript 6(ES6)或ECMAScript 2015(ES2015):第6版ECMAScript,于2015年标准化。这个标准已在大多数现代浏览器中部分实现。

以下是ES5和ES6之间的一些主要区别:

  • 箭头函数和字符串插值:
const greetings=(name)=> {
 return `hello ${name}`;
}
const greetings=name=> `hello ${name}`;
  • 常量

常量在很多方面与其他语言中的常量一样,但有一些需要注意的地方。常量表示对值的“固定引用”。因此,在使用常量时,你实际上可以改变变量所引用的对象的属性,但无法改变引用本身。

const NAMES=[];
NAMES.push("Jim");
console.log(NAMES.length===1); // true
NAMES=["Steve", "John"]; // error
  • 块作用域变量。

新的ES6关键字let允许开发人员声明块级别作用域的变量。let不像var那样可以进行提升。

  • 默认参数值

默认参数允许我们使用默认值初始化函数。如果省略或未定义参数,则使用默认值,也就是说null是有效值。

// 基本语法
function multiply (a, b=2) {
 return a * b;
}
multiply(5); // 10
  • 类定义和继承

ES6引入了对类(关键字class)、构造函数(关键字constructor)和用于继承的extend关键字的支持。

  • for…of操作符

for…of语句将创建一个遍历可迭代对象的循环。

  • 用于对象合并的Spread操作
const obj1={ a: 1, b: 2 }
const obj2={ a: 2, c: 3, d: 4}
const obj3={...obj1, ...obj2}
  • promise

promise提供了一种机制来处理异步操作结果。你可以使用回调来达到同样的目的,但是promise通过方法链接和简洁的错误处理带来了更高的可读性。

const isGreater=(a, b)=> {
return new Promise ((resolve, reject)=> {
 if(a > b) {
 resolve(true)
 } else {
 reject(false)
 }
 })
}
isGreater(1, 2)
.then(result=> {
 console.log('greater')
})
.catch(result=> {
 console.log('smaller')
})
  • 模块导出和导入
const myModule={ x: 1, y: ()=> { console.log('This is ES5') }}
export default myModule;
import myModule from './myModule';

Q15:解释JavaScript中“undefined”和“not defined”之间的区别

难度:???

在JavaScript中,如果你试图使用一个不存在且尚未声明的变量,JavaScript将抛出错误“var name is not defined”,让后脚本将停止运行。但如果你使用typeof undeclared_variable,它将返回undefined。

在进一步讨论之前,先让我们理解声明和定义之间的区别。

“var x”表示一个声明,因为你没有定义它的值是什么,你只是声明它的存在。

var x; // 声明x
console.log(x); //输出: undefined

“var x=1”既是声明又是定义(我们也可以说它是初始化),x变量的声明和赋值相继发生。在JavaScript中,每个变量声明和函数声明都被带到了当前作用域的顶部,然后进行赋值,这个过程被称为提升(hoisting)。

当我们试图访问一个被声明但未被定义的变量时,会出现undefined错误。

var x; // 声明
if(typeof x==='undefined') // 将返回 true

当我们试图引用一个既未声明也未定义的变量时,将会出现not defined错误。

console.log(y); // 输出: ReferenceError: y is not defined

Q16:匿名和命名函数有什么区别?

难度:???

var foo=function() { // 赋给变量foo的匿名函数
 // ..
};
var x=function bar(){ // 赋给变量x的命名函数bar
 // ..
};
foo(); // 实际执行函数
x();

Q17:Javascript中的“闭包”是什么?举个例子?

难度:????

闭包是在另一个函数(称为父函数)中定义的函数,并且可以访问在父函数作用域中声明和定义的变量。

闭包可以访问三个作用域中的变量:

  • 在自己作用域中声明的变量;
  • 在父函数中声明的变量;
  • 在全局作用域中声明的变量。
var globalVar="abc";
// 自调用函数
(function outerFunction (outerArg) { // outerFunction作用域开始
 // 在outerFunction函数作用域中声明的变量
 var outerFuncVar='x'; 
 // 闭包自调用函数
 (function innerFunction (innerArg) { // innerFunction作用域开始
 // 在innerFunction函数作用域中声明的变量
 var innerFuncVar="y";
 console.log( 
 "outerArg=" + outerArg + "\n" +
 "outerFuncVar=" + outerFuncVar + "\n" +
 "innerArg=" + innerArg + "\n" +
 "innerFuncVar=" + innerFuncVar + "\n" +
 "globalVar=" + globalVar);
 // innerFunction作用域结束
 })(5); // 将5作为参数
// outerFunction作用域结束
})(7); // 将7作为参数

innerFunction是在outerFunction中定义的闭包,可以访问在outerFunction作用域内声明和定义的所有变量。除此之外,闭包还可以访问在全局命名空间中声明的变量。

上述代码的输出将是:

outerArg=7
outerFuncVar=x
innerArg=5
innerFuncVar=y
globalVar=abc

Q18:如何在JavaScript中创建私有变量?

难度:????

要在JavaScript中创建无法被修改的私有变量,你需要将其创建为函数中的局部变量。即使这个函数被调用,也无法在函数之外访问这个变量。例如:

function func() {
 var priv="secret code";
}
console.log(priv); // throws error

要访问这个变量,需要创建一个返回私有变量的辅助函数。

function func() {
 var priv="secret code";
 return function() {
 return priv;
 }
}
var getPriv=func();
console.log(getPriv()); //=> secret code

Q19:请解释原型设计模式

难度:????

原型模式可用于创建新对象,但它创建的不是非初始化的对象,而是使用原型对象(或样本对象)的值进行初始化的对象。原型模式也称为属性模式。

原型模式在初始化业务对象时非常有用,业务对象的值与数据库中的默认值相匹配。原型对象中的默认值被复制到新创建的业务对象中。

经典的编程语言很少使用原型模式,但作为原型语言的JavaScript在构造新对象及其原型时使用了这个模式。


Q20:判断一个给定的字符串是否是同构的

难度:????

如果两个字符串是同构的,那么字符串A中所有出现的字符都可以用另一个字符替换,以便获得字符串B,而且必须保留字符的顺序。字符串A中的每个字符必须与字符串B的每个字符一对一对应。

  • paper和title将返回true。
  • egg和sad将返回false。
  • dgg和add将返回true。
isIsomorphic("egg", 'add'); // true
isIsomorphic("paper", 'title'); // true
isIsomorphic("kick", 'side'); // false
function isIsomorphic(firstString, secondString) {
 // 检查长度是否相等,如果不相等, 它们不可能是同构的
 if (firstString.length !==secondString.length) return false
 var letterMap={};
 for (var i=0; i < firstString.length; i++) {
 var letterA=firstString[i],
 letterB=secondString[i];
 // 如果letterA不存在, 创建一个map,并将letterB赋值给它
 if (letterMap[letterA]===undefined) {
 letterMap[letterA]=letterB;
 } else if (letterMap[letterA] !==letterB) {
 // 如果letterA在map中已存在, 但不是与letterB对应,
 // 那么这意味着letterA与多个字符相对应。
 return false;
 }
 }
 // 迭代完毕,如果满足条件,那么返回true。
 // 它们是同构的。
 return true;
}

Q21:“Transpiling”是什么意思?

难度:????

对于语言中新加入的语法,无法进行polyfill。因此,更好的办法是使用一种工具,可以将较新代码转换为较旧的等效代码。这个过程通常称为转换(transpiling),就是transforming + compiling的意思。

通常,你会将转换器(transpiler)加入到构建过程中,类似于linter或minifier。现在有很多很棒的转换器可选择:

  • Babel:将ES6+转换为ES5
  • Traceur:将ES6、ES7转换为ES5

Q22:“this”关键字的原理是什么?请提供一些代码示例。

难度:????

在JavaScript中,this是指正在执行的函数的“所有者”,或者更确切地说,指将当前函数作为方法的对象。

function foo() {
 console.log( this.bar );
}
var bar="global";
var obj1={
 bar: "obj1",
 foo: foo
};
var obj2={
 bar: "obj2"
};
foo(); // "global"
obj1.foo(); // "obj1"
foo.call( obj2 ); // "obj2"
new foo(); // undefined

Q23:如何向Array对象添加自定义方法,让下面的代码可以运行?

难度:????

var arr=[1, 2, 3, 4, 5];
var avg=arr.average();
console.log(avg);

JavaScript不是基于类的,但它是基于原型的语言。这意味着每个对象都链接到另一个对象(也就是对象的原型),并继承原型对象的方法。你可以跟踪每个对象的原型链,直到到达没有原型的null对象。我们需要通过修改Array原型来向全局Array对象添加方法。

Array.prototype.average=function() {
 // 计算sum的值
 var sum=this.reduce(function(prev, cur) { return prev + cur; });
 // 将sum除以元素个数并返回
 return sum / this.length;
}
var arr=[1, 2, 3, 4, 5];
var avg=arr.average();
console.log(avg); //=> 3

Q24:什么是JavaScript中的提升操作?

难度:????

提升(hoisting)是JavaScript解释器将所有变量和函数声明移动到当前作用域顶部的操作。有两种类型的提升:

  • 变量提升——非常少见
  • 函数提升——更常见

无论var(或函数声明)出现在作用域的什么地方,它都属于整个作用域,并且可以在该作用域内的任何地方访问它。

var a=2;
foo(); // 因为`foo()`声明被"提升",所以可调用
function foo() {
 a=3;
 console.log( a ); // 3
 var a; // 声明被"提升"到foo()的顶部
}
console.log( a ); // 2

Q25:以下代码输出的结果是什么?

难度:????

0.1 + 0.2===0.3

这段代码的输出是false,这是由浮点数内部表示导致的。0.1 + 0.2并不刚好等于0.3,实际结果是0.30000000000000004。解决这个问题的一个办法是在对小数进行算术运算时对结果进行舍入。


Q26:请描述一下Revealing Module Pattern设计模式

难度:?????

暴露模块模式(Revealing Module Pattern)是模块模式的一个变体,目的是维护封装性并暴露在对象中返回的某些变量和方法。如下所示:

var Exposer=(function() {
 var privateVariable=10;
 var privateMethod=function() {
 console.log('Inside a private method!');
 privateVariable++;
 }
 var methodToExpose=function() {
 console.log('This is a method I want to expose!');
 }
 var otherMethodIWantToExpose=function() {
 privateMethod();
 }
 return {
 first: methodToExpose,
 second: otherMethodIWantToExpose
 };
})();
Exposer.first(); // 输出: This is a method I want to expose!
Exposer.second(); // 输出: Inside a private method!
Exposer.methodToExpose; // undefined

它的一个明显的缺点是无法引用私有方法。

英文原文:https://www.fullstack.cafe/blog/top-26-javascript-interview-questions-and-answers-in-2019

加米谷大数据培训机构,小班教学创始人面授,10月22日成都大数据开发零基础班预报名进行中...

JsBarcode是一个用JavaScript编写的条形码生成器。它支持多种条形码格式,可在浏览器和Node.js中使用。如果你在项目中使用了jquery也可以使用jquery,但它不是依赖项。

github

https://github.com/lindell/JsBarcode

支持的条形码种类

  • CODE128
  • CODE128 (automatic mode switching)
  • CODE128 A/B/C (force mode)
  • EAN
  • EAN-13
  • EAN-8
  • EAN-5
  • EAN-2
  • UPC (A)
  • UPC (E)
  • CODE39
  • ITF
  • ITF
  • ITF-14
  • MSI
  • MSI10
  • MSI11
  • MSI1010
  • MSI1110
  • Pharmacode
  • Codabar

浏览器中使用举例

  • 通过svg、canvas、img都可以
<svg id="barcode"></svg>
<!-- or -->
<canvas id="barcode"></canvas>
<!-- or -->
<img id="barcode"/>
JsBarcode("#barcode", "Hi!");
// or with jQuery
$("#barcode").JsBarcode("Hi!");
JsBarcode("#barcode", "1234", {
 format: "pharmacode",
 lineColor: "#0aa",
 width:4,
 height:40,
 displayValue: false
});

  • 你也可以使用一些自定义的配置
JsBarcode("#barcode", "1234", {
 format: "pharmacode",
 lineColor: "#0aa",
 width:4,
 height:40,
 displayValue: false
});

  • 更高级的用法
JsBarcode("#barcode")
 .options({font: "OCR-B"}) // Will affect all barcodes
 .EAN13("1234567890128", {fontSize: 18, textMargin: 0})
 .blank(20) // Create space between the barcodes
 .EAN5("12345", {height: 85, textPosition: "top", fontSize: 16, marginTop: 15})
 .render();

  • 直接在html标签中使用
<svg class="barcode"
 jsbarcode-format="upc"
 jsbarcode-value="123456789012"
 jsbarcode-textmargin="0"
 jsbarcode-fontoptions="bold">
</svg>

初始化还是需要的

JsBarcode(".barcode").init();

安装使用

  • 浏览器使用

你可以下载完整的支持所有受支持的条形码,也可以下载特定的条形码,根据自己的需要进行下载,具体的下载地址可以到github下载。

浏览器引入

<script src="JsBarcode.all.min.js"></script>

使用broser或者npm包管理

bower install jsbarcode --save
npm install jsbarcode --save
  • nodejs使用

首先你的安装jsbarcode和canvas

npm install jsbarcode
npm install canvas

使用简单案例

var JsBarcode=require('jsbarcode');
// Canvas v1
var Canvas=require("canvas");
// Canvas v2
var { createCanvas }=require("canvas");
// Canvas v1
var canvas=new Canvas();
// Canvas v2
var canvas=createCanvas();
JsBarcode(canvas, "Hello");

所有配置项

总结

JSBarcode是一个条形码JavaScript中的条形码生成插件,支持浏览器端和nodejs,在很多业务场景下都可以使用到,非常的简单实用!希望对你有所帮助!

又一次跪在坟前。

一边哭,一边发誓:“我一定要完成你的遗愿!”

那年,他13岁。

站在广西的山头,放眼望去,茫茫一片青翠。溪水从高处流下,绕山岨流。

任谁看了都要赞一句自然好风光。

可现实也是:肉眼可见的贫困。

他在这里长大。

小小年纪,便扮演了多个角色——

孤儿。学生。拾荒者。

听了他的故事,人们皆叹:人间多苦,磨难不绝。

他叫韦仁龙。一个即将创造奇迹的寒门学子。

但在故事之初,没有人知道,他的道路漫长而灿烂。

人们只知道,他们家太穷了。

那个年代的山村,很少有人不苦。

他们家更甚。

面朝黄土背朝天,是无法选择的宿命。

作为底层农民,家中添丁,是喜也是愁。

喜的是生了个孩子,愁的是生活压力山大。

韦仁龙降生时,父亲抱着他,眼含热泪,发誓要给儿子一个不同的人生。

于是,踏上了外出打工的征途。

他想赚很多钱,给儿子买书。

但一年后,钱没赚到,等到的是父亲猝然离世。

噩耗传回小山村,年轻的母亲哭得昏了过去。

尚在襁褓中的韦仁龙,此时还不知道,人生的第一记重创,已经来临。

失去顶梁柱,意味着失去经济来源。

孤儿寡母,应该何去何从?

“嫁人吧。”亲友劝韦仁龙的母亲。

挣扎了一段时间后,她含泪松口,只提出了一个条件——

“要对我儿子好。”

亲友替她费心打听。

有人说,同村的韦双锦还不错。

他单身寡佬,为人忠厚老实,与韦仁龙有相似的经历。

同样幼时父母双亡,吃百家饭长大,应该能感同身受他们的不易。

最后,双方都点了头。

一个贫困又幸福的三口之家,就此组建。

继父对他不错,视如己出。

青山绿水间,继父常常将他扛在肩头,登高摘果,山涧戏水。

母亲很满足。

为了分担丈夫的养家压力,她会去村里帮人弹棉花。

轻轻一动,就丝絮纷飞。

这些尘屑侵入她的呼吸道,天长日久,她和亡夫一样,患上了肺病。

一到半夜,咳血不止。

韦双锦放心不下,带着她赶往镇上的医院。

很快,检查结果出来了。

肺癌晚期。

医生说,希望不大。

韦双锦不信。

他到处跟人借钱,只要能治好妻子的病,他什么都愿意做。

可惜,上天没有怜悯这份深情,还是残忍地让他失去挚爱。

韦仁龙也失去了母亲。

那年他3岁,尚不懂父母双亡,到底意味着什么。

当门前不再有人等候,当灯下不再有人缝补,当不再有人温柔地追着他喂饭。

他才开始哭闹寻找。

继父只能编了善意的谎言:“她去外地做事了。”

自己却在静谧的深夜,睁眼到天明。

天亮了。继父不得不为生计发愁,更要为韦仁龙的未来担忧。

听村里的人说,海南赚钱机会多,他决定南下。

儿子才3岁,一个人在家也不行。于是,带着他一起前往海南。

白天,父亲在工地打工。

晚上,儿子在家做好饭。

有时候,为了分担压力,小小的孩子也会去工地附近,捡一些垃圾卖钱。

那时,韦仁龙才4岁。

转眼间,那个比灶台还矮的小不点,已经到了上学的年纪。

韦双锦开始为他物色学校。

但当地的高额学费,让他望而却步。

此时,他已疾病缠身,无法再从事高强度工作。

相依为命的父子二人,干脆回了老家。

儿子到学校读书,父亲回田里干活。

放学后,韦仁龙总会飞奔到田里。

继父插秧,他读书。

伴着稻穗的香气,朗朗读书声尤其悦耳。

韦双锦很欣慰。

他总是对韦仁龙说:

“知识改变命运。一定要好好读书,考上好大学。”

韦仁龙都记在心里。他吃够了生活的苦,很早慧,也努力。

成绩一直名列前茅。

父子俩坚定地相信,一切都会慢慢变好。

可噩梦,总是猝不及防。

积劳成疾的厄运,再次降临这个苦命的家庭。

韦双锦因病重,离世了。

只留下一亩农田、一间四面漏风的土屋和一个失去生父、生母、继父的孤儿。

村里人都可怜他,帮着韦仁龙,为继父办了一场葬礼。

孩子哭得昏天暗地。

他抱着继父的遗体哭喊:“不要留下我一个人。”

舅公于心不忍,提出要收养他。

韦仁龙拒绝了。

一来,舅公自己也家境贫寒。

二来,他还有三个孩子要养。再收养一个,生活实在无法维持。

韦仁龙懂。

所以故作坚强地说:“我自己一个人也能活下去。”

话音刚落,转身踏上泥泞的回家路。

这条路,谈何容易。

但韦仁龙以超人的意志,扛了下来。

因内向,也因自尊,他未曾向人求助,一个人迎向生活的狂风暴雨。

回到家,他卷起裤脚,脱下布鞋,牵了那头耕牛,往田里走去。

脚印踩在田中,来来回回,重重叠叠。

天色渐晚,孩子与老牛相伴归家。

饿了,就在屋后挖野菜。渴了,就到山上摘野果。

没钱买水壶、水杯,就砍一节竹子来用。

为了加些营养,他还会冒险到山涧抓小螃蟹。

蚂蟥蜇满他的脚,咬得鲜血淋漓。

这些之于韦仁龙,都是家常便饭。

生活举步维艰,还上学吗?

上,必须上。

可没有学费怎么办?

自己攒。

饭卡没有钱,怎么办?

饿着。

他从一天三顿,变成一天两顿,又变成一天一顿。

后来,干脆不吃。

有时,两三天都没吃饭,饿得双眼发花。

同桌经常听到他肚子饿得咕咕响。

他常听人说:“书是精神食粮。”

饿得不行时,他就捧着书读,一直读到太阳下山。

实在扛不住了,去食堂捡一点烂菜叶,或者将一个冷馒头分成几次吃。

回家路上,途经水果摊。

他总问老板:“这个水果烂了,你别扔,可以给我吃吗?”

老板心疼这个可怜的孩子,有时,还会送一些没坏的水果给他。

后来,韦仁龙不敢再收了。

一来,老板赚钱不易;二来,怕别人效仿他。

他想靠自己活下去。

放学后,他就跑到山上摘八角。

背回来后摊平晒干,一斤能换六七块。

他还会经常去垃圾堆捡垃圾卖钱。

附近的垃圾捡完了,就去邻村继续捡,再提到废品站卖掉。

靠这些方式,他一点一点为自己攒学费。

捡垃圾时,他太饿了,就会翻一翻有没有别人丢弃的食物。

但没有。食物往往都吃干净了。

偶尔能捡到一两支铅笔,他如获至宝,因为自己写字用得上。

后来,他还留下一个最大的矿泉水瓶,当作自己的存钱罐。

里面一角、两角的,装着他通过卖苦力换来的钱。

金额不多,只有100元。

但瓶子的容量很大,装着一个上学的梦想。

他说:“这些钱,可以撑3个月。”

上了初中,学费怎么办,生活费怎么办呢?

“我也可以继续赚。”

他还考虑过:“没有钱读了,我会让学校宽容我几天,出去打零工赚钱,然后再来上学。”

“过一段时间,又没钱了,我会再出去打零工,再回来上学。”

他知道,上学,是他唯一的出路。

那几年里,韦仁龙捡了成千上万个瓶子。也去附近工地,帮了不知多少次的工。

命运提前在少年面前,铺开重重困境。

他没有被吓退,依然咬紧牙关,拼命学习。

校长说:“他很有天赋,品学兼优。”

“我考上好学校,这是我爸最大的愿望。”

昏黄灯光下,他想起继父的嘱托,不禁又流下眼泪。

亲人的离世,生活的艰苦,压弯了少年的脊背。

而社会的温暖,让他坚定地挺起胸膛。

后来,学校终于知道了他的困境,全校师生为他捐款。

这1480.5元,一度把他从辍学边缘拉了回来。

同时,他的事被电视台知晓。

他登上“第一书记”节目,讲出了自己的故事。

节目现场,爱心人士当场向他捐赠两万元。

这就意味着,他可以继续上学了。

上初中要离开大山。

临行前,他来到继父的坟前。

没有把苦楚说与他听,只倾诉了无尽的思念。

“爸,我要去更远的地方读书了。可能很久都不能来看你。无论我走多远,这里永远都是我的家。”

“我不会忘记你对我有多好。”

他叩了头,下了山,回到校园。

在学校里,他一如既往,非常用功。

别人用兴趣学习,他用命学习。

在无人关注的地方,他挥汗如雨,目标坚定。

世界上没有任何困难,能难倒一个坚韧又聪明的孩子。也没有任何障碍,能挡住一个不达目的誓不罢休的人。

后来我们听到的,都是关于韦仁龙的好消息。

他考上县重点,依然成绩拔尖。

再后来,有传闻,他以707的高分,考上了北京大学。

韦仁龙,终于逆袭。无数人激动万分。

谁说逆境不能出人才?

你看,这不就是!

只要一个人意志够强,决心够狠,就一定能站在梦想的高地。

后来,也有人解释说,他考上的,实际不是北京大学,而是华南理工大学。

说法不一。

对此,韦仁龙本人并没有回应。

但不论结局如何,之于他,命运的结局已经改写。

之于我们,最牵挂的孤儿,成功创造了奇迹般的人生。

已经足矣。

犹记得,他在广西卫视的节目里,跪在坟前,对继父发誓:

“我一定要完成你的遗愿。”

几年过去,他如愿以偿。

继父应该可以含笑九泉,生父生母,也可以安息了。

此时,群山之下,道路曲折地通向远方。

他走上去,渐行渐远。

我们相信——

在他的身后,无数大山里学子,正在紧随而来......

因为他已经告诉无数人,天再黑,星辰也会亮。只要不放弃,只要坚持前行,就一定能看到光。

参考资料:

707分考入北大,自幼父母双亡拾破烂为生,韦仁龙是如何逆袭的?

https://www.163.com/dy/article/GUN574NH0552BGPW.html

父母双亡苦仁龙, 独自踏上求学路!真人真事!

https://v.qq.com/x/page/d0522a8jz71.html

《第一书记》韦仁龙:父母双亡苦仁龙 独自踏上求学路

https://mp.weixin.qq.com/s/hsTBRKfX1KIPHW8TNqhQow

捡垃圾考上北大,广西寒门再出高考状元

https://k.sina.com.cn/article_7021891231_1a2898e9f00101343l.html

【4K氛围白噪音】远山炊烟 治愈的乡村烟火气息

https://www.bilibili.com/video/BV1VT4y1f7Aj?spm_id_from=333.788.top_right_bar_window_custom_collection.content.click

来源:周冲的影像声色,一个文艺而理性的原创公号。