據(jù)Stack Overflow的2018年度調(diào)查,JavaScript連續(xù)六年成為最常用的編程語言。所以我們必須面對這樣的現(xiàn)實(shí),JavaScript已經(jīng)成為全棧開發(fā)技能的基石,在全棧開發(fā)面試中都會(huì)不可避免地涉及到與JavaScript有關(guān)的問題。
FullStack.Cafe匯編了最常見的JavaScript面試問題和答案,希望能夠幫助讀者找到下一份夢想中的工作。
編程工程概念
Q1:JavaScript中的強(qiáng)制轉(zhuǎn)型(coercion)是指什么?
難度:0
在JavaScript中,兩種不同的內(nèi)置類型間的轉(zhuǎn)換被稱為強(qiáng)制轉(zhuǎn)型。強(qiáng)制轉(zhuǎn)型在JavaScript中有兩種形式:顯式和隱式。
這是一個(gè)顯式強(qiáng)制轉(zhuǎn)型的例子:
var a="42"; var b=Number( a ); a; // "42" b; // 42 -- 是個(gè)數(shù)字!
這是一個(gè)隱式強(qiáng)制轉(zhuǎn)型的例子:
var a="42"; var b=a * 1; // "42" 隱式轉(zhuǎn)型成 42 a; // "42" b; // 42 -- 是個(gè)數(shù)字!
Q2:JavaScript中的作用域(scope)是指什么?
難度:?
在JavaScript中,每個(gè)函數(shù)都有自己的作用域。作用域基本上是變量以及如何通過名稱訪問這些變量的規(guī)則的集合。只有函數(shù)中的代碼才能訪問函數(shù)作用域內(nèi)的變量。
同一個(gè)作用域中的變量名必須是唯一的。一個(gè)作用域可以嵌套在另一個(gè)作用域內(nèi)。如果一個(gè)作用域嵌套在另一個(gè)作用域內(nèi),最內(nèi)部作用域內(nèi)的代碼可以訪問另一個(gè)作用域的變量。
Q3:解釋JavaScript中的相等性
難度:?
JavaScript中有嚴(yán)格比較和類型轉(zhuǎn)換比較:
var a="42"; var b=42; a==b; // true a===b; // false
一些簡單的規(guī)則:
Q4:解釋什么是回調(diào)函數(shù),并提供一個(gè)簡單的例子。
難度:??
回調(diào)函數(shù)是可以作為參數(shù)傳遞給另一個(gè)函數(shù)的函數(shù),并在某些操作完成后執(zhí)行。下面是一個(gè)簡單的回調(diào)函數(shù)示例,這個(gè)函數(shù)在某些操作完成后打印消息到控制臺(tái)。
function modifyArray(arr, callback) { // 對arr做一些操作 arr.push(100); // 執(zhí)行傳進(jìn)來的callback函數(shù) callback(); } var arr=[1, 2, 3, 4, 5]; modifyArray(arr, function() { console.log("array has been modified", arr); });
Q5:“use strict”的作用是什么?
難度:??
use strict出現(xiàn)在JavaScript代碼的頂部或函數(shù)的頂部,可以幫助你寫出更安全的JavaScript代碼。如果你錯(cuò)誤地創(chuàng)建了全局變量,它會(huì)通過拋出錯(cuò)誤的方式來警告你。例如,以下程序?qū)伋鲥e(cuò)誤:
function doSomething(val) { "use strict"; x=val + 10; }
它會(huì)拋出一個(gè)錯(cuò)誤,因?yàn)閤沒有被定義,并使用了全局作用域中的某個(gè)值對其進(jìn)行賦值,而use strict不允許這樣做。下面的小改動(dòng)修復(fù)了這個(gè)錯(cuò)誤:
function doSomething(val) { "use strict"; var x=val + 10; }
Q6:解釋JavaScript中的null和undefined
難度:??
JavaScript中有兩種底層類型:null和undefined。它們代表了不同的含義:
Q7:編寫一個(gè)可以執(zhí)行如下操作的函數(shù)。
難度:??
var addSix=createBase(6); addSix(10); // 返回16 addSix(21); // 返回27
可以創(chuàng)建一個(gè)閉包來存放傳遞給函數(shù)createBase的值。被返回的內(nèi)部函數(shù)是在外部函數(shù)中創(chuàng)建的,內(nèi)部函數(shù)就成了一個(gè)閉包,它可以訪問外部函數(shù)中的變量,在本例中是變量baseNumber。
function createBase(baseNumber) { return function(N) { // 我們在這里訪問baseNumber,即使它是在這個(gè)函數(shù)之外聲明的。 // JavaScript中的閉包允許我們這么做。 return baseNumber + N; } } var addSix=createBase(6); addSix(10); addSix(21);
Q8:解釋JavaScript中的值和類型
難度:??
JavaScript有類型值,但沒有類型變量。JavaScript提供了以下幾種內(nèi)置類型:
Q9:解釋事件冒泡以及如何阻止它
難度:??
事件冒泡是指嵌套最深的元素觸發(fā)一個(gè)事件,然后這個(gè)事件順著嵌套順序在父元素上觸發(fā)。
防止事件冒泡的一種方法是使用event.cancelBubble或event.stopPropagation()(低于IE 9)。
Q10:JavaScript中的let關(guān)鍵字有什么用?
難度:??
除了可以在函數(shù)級別聲明變量之外,ES6還允許你使用let關(guān)鍵字在代碼塊({..})中聲明變量。
Q11:如何檢查一個(gè)數(shù)字是否為整數(shù)?
難度:??
檢查一個(gè)數(shù)字是小數(shù)還是整數(shù),可以使用一種非常簡單的方法,就是將它對1進(jìn)行取模,看看是否有余數(shù)。
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(立即調(diào)用函數(shù)表達(dá)式)?
難度:???
它是立即調(diào)用函數(shù)表達(dá)式(Immediately-Invoked Function Expression),簡稱IIFE。函數(shù)被創(chuàng)建后立即被執(zhí)行:
(function IIFE(){ console.log( "Hello!" ); })(); // "Hello!"
在避免污染全局命名空間時(shí)經(jīng)常使用這種模式,因?yàn)镮IFE(與任何其他正常函數(shù)一樣)內(nèi)部的所有變量在其作用域之外都是不可見的。
Q13:如何在JavaScript中比較兩個(gè)對象?
難度:???
對于兩個(gè)非原始值,比如兩個(gè)對象(包括函數(shù)和數(shù)組),==和===比較都只是檢查它們的引用是否匹配,并不會(huì)檢查實(shí)際引用的內(nèi)容。
例如,默認(rèn)情況下,數(shù)組將被強(qiáng)制轉(zhuǎn)型成字符串,并使用逗號將數(shù)組的所有元素連接起來。所以,兩個(gè)具有相同內(nèi)容的數(shù)組進(jìn)行==比較時(shí)不會(huì)相等:
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這個(gè)庫,或者自己實(shí)現(xiàn)遞歸比較算法。
Q14:你能解釋一下ES5和ES6之間的區(qū)別嗎?
難度:???
以下是ES5和ES6之間的一些主要區(qū)別:
const greetings=(name)=> { return `hello ${name}`; } const greetings=name=> `hello ${name}`;
常量在很多方面與其他語言中的常量一樣,但有一些需要注意的地方。常量表示對值的“固定引用”。因此,在使用常量時(shí),你實(shí)際上可以改變變量所引用的對象的屬性,但無法改變引用本身。
const NAMES=[]; NAMES.push("Jim"); console.log(NAMES.length===1); // true NAMES=["Steve", "John"]; // error
新的ES6關(guān)鍵字let允許開發(fā)人員聲明塊級別作用域的變量。let不像var那樣可以進(jìn)行提升。
默認(rèn)參數(shù)允許我們使用默認(rèn)值初始化函數(shù)。如果省略或未定義參數(shù),則使用默認(rèn)值,也就是說null是有效值。
// 基本語法 function multiply (a, b=2) { return a * b; } multiply(5); // 10
ES6引入了對類(關(guān)鍵字class)、構(gòu)造函數(shù)(關(guān)鍵字constructor)和用于繼承的extend關(guān)鍵字的支持。
for…of語句將創(chuàng)建一個(gè)遍歷可迭代對象的循環(huán)。
const obj1={ a: 1, b: 2 } const obj2={ a: 2, c: 3, d: 4} const obj3={...obj1, ...obj2}
promise提供了一種機(jī)制來處理異步操作結(jié)果。你可以使用回調(diào)來達(dá)到同樣的目的,但是promise通過方法鏈接和簡潔的錯(cuò)誤處理帶來了更高的可讀性。
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”之間的區(qū)別
難度:???
在JavaScript中,如果你試圖使用一個(gè)不存在且尚未聲明的變量,JavaScript將拋出錯(cuò)誤“var name is not defined”,讓后腳本將停止運(yùn)行。但如果你使用typeof undeclared_variable,它將返回undefined。
在進(jìn)一步討論之前,先讓我們理解聲明和定義之間的區(qū)別。
“var x”表示一個(gè)聲明,因?yàn)槟銢]有定義它的值是什么,你只是聲明它的存在。
var x; // 聲明x console.log(x); //輸出: undefined
“var x=1”既是聲明又是定義(我們也可以說它是初始化),x變量的聲明和賦值相繼發(fā)生。在JavaScript中,每個(gè)變量聲明和函數(shù)聲明都被帶到了當(dāng)前作用域的頂部,然后進(jìn)行賦值,這個(gè)過程被稱為提升(hoisting)。
當(dāng)我們試圖訪問一個(gè)被聲明但未被定義的變量時(shí),會(huì)出現(xiàn)undefined錯(cuò)誤。
var x; // 聲明 if(typeof x==='undefined') // 將返回 true
當(dāng)我們試圖引用一個(gè)既未聲明也未定義的變量時(shí),將會(huì)出現(xiàn)not defined錯(cuò)誤。
console.log(y); // 輸出: ReferenceError: y is not defined
Q16:匿名和命名函數(shù)有什么區(qū)別?
難度:???
var foo=function() { // 賦給變量foo的匿名函數(shù) // .. }; var x=function bar(){ // 賦給變量x的命名函數(shù)bar // .. }; foo(); // 實(shí)際執(zhí)行函數(shù) x();
Q17:Javascript中的“閉包”是什么?舉個(gè)例子?
難度:????
閉包是在另一個(gè)函數(shù)(稱為父函數(shù))中定義的函數(shù),并且可以訪問在父函數(shù)作用域中聲明和定義的變量。
閉包可以訪問三個(gè)作用域中的變量:
var globalVar="abc"; // 自調(diào)用函數(shù) (function outerFunction (outerArg) { // outerFunction作用域開始 // 在outerFunction函數(shù)作用域中聲明的變量 var outerFuncVar='x'; // 閉包自調(diào)用函數(shù) (function innerFunction (innerArg) { // innerFunction作用域開始 // 在innerFunction函數(shù)作用域中聲明的變量 var innerFuncVar="y"; console.log( "outerArg=" + outerArg + "\n" + "outerFuncVar=" + outerFuncVar + "\n" + "innerArg=" + innerArg + "\n" + "innerFuncVar=" + innerFuncVar + "\n" + "globalVar=" + globalVar); // innerFunction作用域結(jié)束 })(5); // 將5作為參數(shù) // outerFunction作用域結(jié)束 })(7); // 將7作為參數(shù)
innerFunction是在outerFunction中定義的閉包,可以訪問在outerFunction作用域內(nèi)聲明和定義的所有變量。除此之外,閉包還可以訪問在全局命名空間中聲明的變量。
上述代碼的輸出將是:
outerArg=7 outerFuncVar=x innerArg=5 innerFuncVar=y globalVar=abc
Q18:如何在JavaScript中創(chuàng)建私有變量?
難度:????
要在JavaScript中創(chuàng)建無法被修改的私有變量,你需要將其創(chuàng)建為函數(shù)中的局部變量。即使這個(gè)函數(shù)被調(diào)用,也無法在函數(shù)之外訪問這個(gè)變量。例如:
function func() { var priv="secret code"; } console.log(priv); // throws error
要訪問這個(gè)變量,需要?jiǎng)?chuàng)建一個(gè)返回私有變量的輔助函數(shù)。
function func() { var priv="secret code"; return function() { return priv; } } var getPriv=func(); console.log(getPriv()); //=> secret code
Q19:請解釋原型設(shè)計(jì)模式
難度:????
原型模式可用于創(chuàng)建新對象,但它創(chuàng)建的不是非初始化的對象,而是使用原型對象(或樣本對象)的值進(jìn)行初始化的對象。原型模式也稱為屬性模式。
原型模式在初始化業(yè)務(wù)對象時(shí)非常有用,業(yè)務(wù)對象的值與數(shù)據(jù)庫中的默認(rèn)值相匹配。原型對象中的默認(rèn)值被復(fù)制到新創(chuàng)建的業(yè)務(wù)對象中。
經(jīng)典的編程語言很少使用原型模式,但作為原型語言的JavaScript在構(gòu)造新對象及其原型時(shí)使用了這個(gè)模式。
Q20:判斷一個(gè)給定的字符串是否是同構(gòu)的
難度:????
如果兩個(gè)字符串是同構(gòu)的,那么字符串A中所有出現(xiàn)的字符都可以用另一個(gè)字符替換,以便獲得字符串B,而且必須保留字符的順序。字符串A中的每個(gè)字符必須與字符串B的每個(gè)字符一對一對應(yīng)。
isIsomorphic("egg", 'add'); // true isIsomorphic("paper", 'title'); // true isIsomorphic("kick", 'side'); // false function isIsomorphic(firstString, secondString) { // 檢查長度是否相等,如果不相等, 它們不可能是同構(gòu)的 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不存在, 創(chuàng)建一個(gè)map,并將letterB賦值給它 if (letterMap[letterA]===undefined) { letterMap[letterA]=letterB; } else if (letterMap[letterA] !==letterB) { // 如果letterA在map中已存在, 但不是與letterB對應(yīng), // 那么這意味著letterA與多個(gè)字符相對應(yīng)。 return false; } } // 迭代完畢,如果滿足條件,那么返回true。 // 它們是同構(gòu)的。 return true; }
Q21:“Transpiling”是什么意思?
難度:????
對于語言中新加入的語法,無法進(jìn)行polyfill。因此,更好的辦法是使用一種工具,可以將較新代碼轉(zhuǎn)換為較舊的等效代碼。這個(gè)過程通常稱為轉(zhuǎn)換(transpiling),就是transforming + compiling的意思。
通常,你會(huì)將轉(zhuǎn)換器(transpiler)加入到構(gòu)建過程中,類似于linter或minifier。現(xiàn)在有很多很棒的轉(zhuǎn)換器可選擇:
Q22:“this”關(guān)鍵字的原理是什么?請?zhí)峁┮恍┐a示例。
難度:????
在JavaScript中,this是指正在執(zhí)行的函數(shù)的“所有者”,或者更確切地說,指將當(dāng)前函數(shù)作為方法的對象。
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對象添加自定義方法,讓下面的代碼可以運(yùn)行?
難度:????
var arr=[1, 2, 3, 4, 5]; var avg=arr.average(); console.log(avg);
JavaScript不是基于類的,但它是基于原型的語言。這意味著每個(gè)對象都鏈接到另一個(gè)對象(也就是對象的原型),并繼承原型對象的方法。你可以跟蹤每個(gè)對象的原型鏈,直到到達(dá)沒有原型的null對象。我們需要通過修改Array原型來向全局Array對象添加方法。
Array.prototype.average=function() { // 計(jì)算sum的值 var sum=this.reduce(function(prev, cur) { return prev + cur; }); // 將sum除以元素個(gè)數(shù)并返回 return sum / this.length; } var arr=[1, 2, 3, 4, 5]; var avg=arr.average(); console.log(avg); //=> 3
Q24:什么是JavaScript中的提升操作?
難度:????
提升(hoisting)是JavaScript解釋器將所有變量和函數(shù)聲明移動(dòng)到當(dāng)前作用域頂部的操作。有兩種類型的提升:
無論var(或函數(shù)聲明)出現(xiàn)在作用域的什么地方,它都屬于整個(gè)作用域,并且可以在該作用域內(nèi)的任何地方訪問它。
var a=2; foo(); // 因?yàn)閌foo()`聲明被"提升",所以可調(diào)用 function foo() { a=3; console.log( a ); // 3 var a; // 聲明被"提升"到foo()的頂部 } console.log( a ); // 2
Q25:以下代碼輸出的結(jié)果是什么?
難度:????
0.1 + 0.2===0.3
這段代碼的輸出是false,這是由浮點(diǎn)數(shù)內(nèi)部表示導(dǎo)致的。0.1 + 0.2并不剛好等于0.3,實(shí)際結(jié)果是0.30000000000000004。解決這個(gè)問題的一個(gè)辦法是在對小數(shù)進(jìn)行算術(shù)運(yùn)算時(shí)對結(jié)果進(jìn)行舍入。
Q26:請描述一下Revealing Module Pattern設(shè)計(jì)模式
難度:?????
暴露模塊模式(Revealing Module Pattern)是模塊模式的一個(gè)變體,目的是維護(hù)封裝性并暴露在對象中返回的某些變量和方法。如下所示:
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
它的一個(gè)明顯的缺點(diǎn)是無法引用私有方法。
英文原文:https://www.fullstack.cafe/blog/top-26-javascript-interview-questions-and-answers-in-2019
加米谷大數(shù)據(jù)培訓(xùn)機(jī)構(gòu),小班教學(xué)創(chuàng)始人面授,10月22日成都大數(shù)據(jù)開發(fā)零基礎(chǔ)班預(yù)報(bào)名進(jìn)行中...
JsBarcode是一個(gè)用JavaScript編寫的條形碼生成器。它支持多種條形碼格式,可在瀏覽器和Node.js中使用。如果你在項(xiàng)目中使用了jquery也可以使用jquery,但它不是依賴項(xiàng)。
https://github.com/lindell/JsBarcode
<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();
<svg class="barcode" jsbarcode-format="upc" jsbarcode-value="123456789012" jsbarcode-textmargin="0" jsbarcode-fontoptions="bold"> </svg>
初始化還是需要的
JsBarcode(".barcode").init();
你可以下載完整的支持所有受支持的條形碼,也可以下載特定的條形碼,根據(jù)自己的需要進(jìn)行下載,具體的下載地址可以到github下載。
瀏覽器引入
<script src="JsBarcode.all.min.js"></script>
使用broser或者npm包管理
bower install jsbarcode --save npm install jsbarcode --save
首先你的安裝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是一個(gè)條形碼JavaScript中的條形碼生成插件,支持瀏覽器端和nodejs,在很多業(yè)務(wù)場景下都可以使用到,非常的簡單實(shí)用!希望對你有所幫助!
又一次跪在墳前。
一邊哭,一邊發(fā)誓:“我一定要完成你的遺愿!”
那年,他13歲。
站在廣西的山頭,放眼望去,茫茫一片青翠。溪水從高處流下,繞山岨流。
任誰看了都要贊一句自然好風(fēng)光。
可現(xiàn)實(shí)也是:肉眼可見的貧困。
他在這里長大。
小小年紀(jì),便扮演了多個(gè)角色——
孤兒。學(xué)生。拾荒者。
聽了他的故事,人們皆嘆:人間多苦,磨難不絕。
他叫韋仁龍。一個(gè)即將創(chuàng)造奇跡的寒門學(xué)子。
但在故事之初,沒有人知道,他的道路漫長而燦爛。
人們只知道,他們家太窮了。
那個(gè)年代的山村,很少有人不苦。
他們家更甚。
面朝黃土背朝天,是無法選擇的宿命。
作為底層農(nóng)民,家中添丁,是喜也是愁。
喜的是生了個(gè)孩子,愁的是生活壓力山大。
韋仁龍降生時(shí),父親抱著他,眼含熱淚,發(fā)誓要給兒子一個(gè)不同的人生。
于是,踏上了外出打工的征途。
他想賺很多錢,給兒子買書。
但一年后,錢沒賺到,等到的是父親猝然離世。
噩耗傳回小山村,年輕的母親哭得昏了過去。
尚在襁褓中的韋仁龍,此時(shí)還不知道,人生的第一記重創(chuàng),已經(jīng)來臨。
失去頂梁柱,意味著失去經(jīng)濟(jì)來源。
孤兒寡母,應(yīng)該何去何從?
“嫁人吧。”親友勸韋仁龍的母親。
掙扎了一段時(shí)間后,她含淚松口,只提出了一個(gè)條件——
“要對我兒子好。”
親友替她費(fèi)心打聽。
有人說,同村的韋雙錦還不錯(cuò)。
他單身寡佬,為人忠厚老實(shí),與韋仁龍有相似的經(jīng)歷。
同樣幼時(shí)父母雙亡,吃百家飯長大,應(yīng)該能感同身受他們的不易。
最后,雙方都點(diǎn)了頭。
一個(gè)貧困又幸福的三口之家,就此組建。
繼父對他不錯(cuò),視如己出。
青山綠水間,繼父常常將他扛在肩頭,登高摘果,山澗戲水。
母親很滿足。
為了分擔(dān)丈夫的養(yǎng)家壓力,她會(huì)去村里幫人彈棉花。
輕輕一動(dòng),就絲絮紛飛。
這些塵屑侵入她的呼吸道,天長日久,她和亡夫一樣,患上了肺病。
一到半夜,咳血不止。
韋雙錦放心不下,帶著她趕往鎮(zhèn)上的醫(yī)院。
很快,檢查結(jié)果出來了。
肺癌晚期。
醫(yī)生說,希望不大。
韋雙錦不信。
他到處跟人借錢,只要能治好妻子的病,他什么都愿意做。
可惜,上天沒有憐憫這份深情,還是殘忍地讓他失去摯愛。
韋仁龍也失去了母親。
那年他3歲,尚不懂父母雙亡,到底意味著什么。
當(dāng)門前不再有人等候,當(dāng)燈下不再有人縫補(bǔ),當(dāng)不再有人溫柔地追著他喂飯。
他才開始哭鬧尋找。
繼父只能編了善意的謊言:“她去外地做事了。”
自己卻在靜謐的深夜,睜眼到天明。
天亮了。繼父不得不為生計(jì)發(fā)愁,更要為韋仁龍的未來擔(dān)憂。
聽村里的人說,海南賺錢機(jī)會(huì)多,他決定南下。
兒子才3歲,一個(gè)人在家也不行。于是,帶著他一起前往海南。
白天,父親在工地打工。
晚上,兒子在家做好飯。
有時(shí)候,為了分擔(dān)壓力,小小的孩子也會(huì)去工地附近,撿一些垃圾賣錢。
那時(shí),韋仁龍才4歲。
轉(zhuǎn)眼間,那個(gè)比灶臺(tái)還矮的小不點(diǎn),已經(jīng)到了上學(xué)的年紀(jì)。
韋雙錦開始為他物色學(xué)校。
但當(dāng)?shù)氐母哳~學(xué)費(fèi),讓他望而卻步。
此時(shí),他已疾病纏身,無法再從事高強(qiáng)度工作。
相依為命的父子二人,干脆回了老家。
兒子到學(xué)校讀書,父親回田里干活。
放學(xué)后,韋仁龍總會(huì)飛奔到田里。
繼父插秧,他讀書。
伴著稻穗的香氣,朗朗讀書聲尤其悅耳。
韋雙錦很欣慰。
他總是對韋仁龍說:
“知識改變命運(yùn)。一定要好好讀書,考上好大學(xué)。”
韋仁龍都記在心里。他吃夠了生活的苦,很早慧,也努力。
成績一直名列前茅。
父子倆堅(jiān)定地相信,一切都會(huì)慢慢變好。
可噩夢,總是猝不及防。
積勞成疾的厄運(yùn),再次降臨這個(gè)苦命的家庭。
韋雙錦因病重,離世了。
只留下一畝農(nóng)田、一間四面漏風(fēng)的土屋和一個(gè)失去生父、生母、繼父的孤兒。
村里人都可憐他,幫著韋仁龍,為繼父辦了一場葬禮。
孩子哭得昏天暗地。
他抱著繼父的遺體哭喊:“不要留下我一個(gè)人。”
舅公于心不忍,提出要收養(yǎng)他。
韋仁龍拒絕了。
一來,舅公自己也家境貧寒。
二來,他還有三個(gè)孩子要養(yǎng)。再收養(yǎng)一個(gè),生活實(shí)在無法維持。
韋仁龍懂。
所以故作堅(jiān)強(qiáng)地說:“我自己一個(gè)人也能活下去。”
話音剛落,轉(zhuǎn)身踏上泥濘的回家路。
這條路,談何容易。
但韋仁龍以超人的意志,扛了下來。
因內(nèi)向,也因自尊,他未曾向人求助,一個(gè)人迎向生活的狂風(fēng)暴雨。
回到家,他卷起褲腳,脫下布鞋,牽了那頭耕牛,往田里走去。
腳印踩在田中,來來回回,重重疊疊。
天色漸晚,孩子與老牛相伴歸家。
餓了,就在屋后挖野菜。渴了,就到山上摘野果。
沒錢買水壺、水杯,就砍一節(jié)竹子來用。
為了加些營養(yǎng),他還會(huì)冒險(xiǎn)到山澗抓小螃蟹。
螞蟥蜇滿他的腳,咬得鮮血淋漓。
這些之于韋仁龍,都是家常便飯。
生活舉步維艱,還上學(xué)嗎?
上,必須上。
可沒有學(xué)費(fèi)怎么辦?
自己攢。
飯卡沒有錢,怎么辦?
餓著。
他從一天三頓,變成一天兩頓,又變成一天一頓。
后來,干脆不吃。
有時(shí),兩三天都沒吃飯,餓得雙眼發(fā)花。
同桌經(jīng)常聽到他肚子餓得咕咕響。
他常聽人說:“書是精神食糧。”
餓得不行時(shí),他就捧著書讀,一直讀到太陽下山。
實(shí)在扛不住了,去食堂撿一點(diǎn)爛菜葉,或者將一個(gè)冷饅頭分成幾次吃。
回家路上,途經(jīng)水果攤。
他總問老板:“這個(gè)水果爛了,你別扔,可以給我吃嗎?”
老板心疼這個(gè)可憐的孩子,有時(shí),還會(huì)送一些沒壞的水果給他。
后來,韋仁龍不敢再收了。
一來,老板賺錢不易;二來,怕別人效仿他。
他想靠自己活下去。
放學(xué)后,他就跑到山上摘八角。
背回來后攤平曬干,一斤能換六七塊。
他還會(huì)經(jīng)常去垃圾堆撿垃圾賣錢。
附近的垃圾撿完了,就去鄰村繼續(xù)撿,再提到廢品站賣掉。
靠這些方式,他一點(diǎn)一點(diǎn)為自己攢學(xué)費(fèi)。
撿垃圾時(shí),他太餓了,就會(huì)翻一翻有沒有別人丟棄的食物。
但沒有。食物往往都吃干凈了。
偶爾能撿到一兩支鉛筆,他如獲至寶,因?yàn)樽约簩懽钟玫蒙稀?/span>
后來,他還留下一個(gè)最大的礦泉水瓶,當(dāng)作自己的存錢罐。
里面一角、兩角的,裝著他通過賣苦力換來的錢。
金額不多,只有100元。
但瓶子的容量很大,裝著一個(gè)上學(xué)的夢想。
他說:“這些錢,可以撐3個(gè)月。”
上了初中,學(xué)費(fèi)怎么辦,生活費(fèi)怎么辦呢?
“我也可以繼續(xù)賺。”
他還考慮過:“沒有錢讀了,我會(huì)讓學(xué)校寬容我?guī)滋欤鋈ゴ蛄愎べ嶅X,然后再來上學(xué)。”
“過一段時(shí)間,又沒錢了,我會(huì)再出去打零工,再回來上學(xué)。”
他知道,上學(xué),是他唯一的出路。
那幾年里,韋仁龍撿了成千上萬個(gè)瓶子。也去附近工地,幫了不知多少次的工。
命運(yùn)提前在少年面前,鋪開重重困境。
他沒有被嚇退,依然咬緊牙關(guān),拼命學(xué)習(xí)。
校長說:“他很有天賦,品學(xué)兼優(yōu)。”
“我考上好學(xué)校,這是我爸最大的愿望。”
昏黃燈光下,他想起繼父的囑托,不禁又流下眼淚。
親人的離世,生活的艱苦,壓彎了少年的脊背。
而社會(huì)的溫暖,讓他堅(jiān)定地挺起胸膛。
后來,學(xué)校終于知道了他的困境,全校師生為他捐款。
這1480.5元,一度把他從輟學(xué)邊緣拉了回來。
同時(shí),他的事被電視臺(tái)知曉。
他登上“第一書記”節(jié)目,講出了自己的故事。
節(jié)目現(xiàn)場,愛心人士當(dāng)場向他捐贈(zèng)兩萬元。
這就意味著,他可以繼續(xù)上學(xué)了。
上初中要離開大山。
臨行前,他來到繼父的墳前。
沒有把苦楚說與他聽,只傾訴了無盡的思念。
“爸,我要去更遠(yuǎn)的地方讀書了。可能很久都不能來看你。無論我走多遠(yuǎn),這里永遠(yuǎn)都是我的家。”
“我不會(huì)忘記你對我有多好。”
他叩了頭,下了山,回到校園。
在學(xué)校里,他一如既往,非常用功。
別人用興趣學(xué)習(xí),他用命學(xué)習(xí)。
在無人關(guān)注的地方,他揮汗如雨,目標(biāo)堅(jiān)定。
世界上沒有任何困難,能難倒一個(gè)堅(jiān)韌又聰明的孩子。也沒有任何障礙,能擋住一個(gè)不達(dá)目的誓不罷休的人。
后來我們聽到的,都是關(guān)于韋仁龍的好消息。
他考上縣重點(diǎn),依然成績拔尖。
再后來,有傳聞,他以707的高分,考上了北京大學(xué)。
韋仁龍,終于逆襲。無數(shù)人激動(dòng)萬分。
誰說逆境不能出人才?
你看,這不就是!
只要一個(gè)人意志夠強(qiáng),決心夠狠,就一定能站在夢想的高地。
后來,也有人解釋說,他考上的,實(shí)際不是北京大學(xué),而是華南理工大學(xué)。
說法不一。
對此,韋仁龍本人并沒有回應(yīng)。
但不論結(jié)局如何,之于他,命運(yùn)的結(jié)局已經(jīng)改寫。
之于我們,最牽掛的孤兒,成功創(chuàng)造了奇跡般的人生。
已經(jīng)足矣。
猶記得,他在廣西衛(wèi)視的節(jié)目里,跪在墳前,對繼父發(fā)誓:
“我一定要完成你的遺愿。”
幾年過去,他如愿以償。
繼父應(yīng)該可以含笑九泉,生父生母,也可以安息了。
此時(shí),群山之下,道路曲折地通向遠(yuǎn)方。
他走上去,漸行漸遠(yuǎn)。
我們相信——
在他的身后,無數(shù)大山里學(xué)子,正在緊隨而來......
因?yàn)樗呀?jīng)告訴無數(shù)人,天再黑,星辰也會(huì)亮。只要不放棄,只要堅(jiān)持前行,就一定能看到光。
參考資料:
707分考入北大,自幼父母雙亡拾破爛為生,韋仁龍是如何逆襲的?
https://www.163.com/dy/article/GUN574NH0552BGPW.html
父母雙亡苦仁龍, 獨(dú)自踏上求學(xué)路!真人真事!
https://v.qq.com/x/page/d0522a8jz71.html
《第一書記》韋仁龍:父母雙亡苦仁龍 獨(dú)自踏上求學(xué)路
https://mp.weixin.qq.com/s/hsTBRKfX1KIPHW8TNqhQow
撿垃圾考上北大,廣西寒門再出高考狀元
https://k.sina.com.cn/article_7021891231_1a2898e9f00101343l.html
【4K氛圍白噪音】遠(yuǎn)山炊煙 治愈的鄉(xiāng)村煙火氣息
https://www.bilibili.com/video/BV1VT4y1f7Aj?spm_id_from=333.788.top_right_bar_window_custom_collection.content.click
來源:周沖的影像聲色,一個(gè)文藝而理性的原創(chuàng)公號。
*請認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。