Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
ÉîÈëÀí½â JavaScript ´íÎóºÍ¶ÑÕ»×·×Ù
 
À´Ô´£ºw3ctech ·¢²¼ÓÚ£º 2017-5-6
  2105  次浏览      27
 

ÓÐʱºòÈËÃDz¢²»¹Ø×¢ÕâЩϸ½Ú£¬µ«Õâ·½ÃæµÄ֪ʶ¿Ï¶¨ÓÐÓã¬ÓÈÆäÊǵ±ÄãÕýÔÚ±àдÓë²âÊÔ»òerrorsÏà¹ØµÄ¿â¡£ÀýÈçÕâ¸öÐÇÆÚÎÒÃǵÄchaiÖгöÏÖÁËÒ»¸öÁîÈ˾ªÌ¾µÄPull Request£¬Ëü´ó´ó¸Ä½øÁËÎÒÃÇ´¦Àí¶ÑÕ»¸ú×ٵķ½Ê½£¬²¢ÔÚÓû§¶ÏÑÔʧ°ÜʱÌṩÁ˸ü¶àµÄÐÅÏ¢¡£

²Ù×÷¶ÑÕ»¼Ç¼¿ÉÒÔÈÃÄãÇåÀíÎÞÓÃÊý¾Ý£¬²¢¼¯Öо«Á¦´¦ÀíÖØÒªÊÂÏî¡£´ËÍ⣬µ±ÄãÕæÕýŪÇå³þError¼°ÆäÊôÐÔ£¬Ä㽫»á¸üÓÐÐÅÐĵØÀûÓÃËü¡£

±¾ÎÄ¿ªÍ·²¿·Ö»òÐíÌ«¹ýÓÚ¼òµ¥£¬µ«µ±Ä㿪ʼ´¦Àí¶ÑÕ»¼Ç¼ʱ£¬Ëü½«±äµÃÉÔ΢ÓÐЩ¸´ÔÓ£¬ËùÒÔÇëÈ·±£ÄãÔÚ¿ªÊ¼Õâ¸öÄDz¿·ÖÕ½Ú֮ǰÒѾ­³ä·ÖÀí½âÇ°ÃæµÄÄÚÈÝ¡£

¶ÑÕ»µ÷ÓÃÈçºÎ¹¤×÷

ÔÚ̸ÂÛerrors֮ǰÎÒÃDZØÐëÃ÷°×¶ÑÕ»µ÷ÓÃÈçºÎ¹¤×÷¡£Ëü·Ç³£¼òµ¥£¬µ«¶ÔÓÚÎÒÃǽ«ÒªÉîÈëµÄÄÚÈݶøÑÔÈ´ÊÇÖÁ¹ØÖØÒªµÄ¡£Èç¹ûÄãÒѾ­ÖªµÀÕⲿ·ÖÄÚÈÝ£¬ÇëËæÊ±Ìø¹ý±¾½Ú¡£

ÿµ±º¯Êý±»µ÷Óã¬Ëü¶¼»á±»ÍƵ½¶ÑÕ»µÄ¶¥²¿¡£º¯ÊýÖ´ÐÐÍê±Ï£¬±ã»á´Ó¶ÑÕ»¶¥²¿ÒƳý¡£

ÕâÖÖÊý¾Ý½á¹¹µÄÓÐȤ֮´¦ÔÚÓÚ×îºóÒ»¸öÈëÕ»µÄ½«»áµÚÒ»¸ö´Ó¶ÑÕ»ÖÐÒÆ³ý£¬ÕâÒ²¾ÍÊÇÎÒÃÇËùÊìϤµÄLIFO(ºó½ø£¬Ïȳö)ÌØÐÔ¡£

ÕâÒ²¾ÍÊÇ˵ÎÒÃÇÔÚº¯ÊýxÖе÷Óú¯Êýy,ÄÇô¶ÔÓ¦µÄ¶ÑÕ»ÖеÄ˳ÐòΪx y¡£

¼ÙÉèÄãÓÐÏÂÃæÕâÑùµÄ´úÂ룺

function c() {   console.log('c');}

function b() { console.log('b'); c();
}

function a() {
console.log('a');
b();
}

a();

ÔÚÉÏÃæÕâÀïÀý×ÓÖУ¬µ±Ö´ÐÐaº¯Êýʱ£¬a±ã»áÌí¼Óµ½¶ÑÕ»µÄ¶¥²¿£¬È»ºóµ±bº¯ÊýÔÚaº¯ÊýÖб»µ÷Óã¬bÒ²»á±»Ìí¼Óµ½¶ÑÕ»µÄ¶¥²¿£¬ÒÀ´ÎÀàÍÆ£¬ÔÚbÖе÷ÓÃcÒ²»á·¢ÉúͬÑùµÄÊÂÇé¡£

µ±cÖ´ÐÐʱ£¬¶ÑÕ»Öеĺ¯ÊýµÄ˳ÐòΪa b c

cÖ´ÐÐÍê±Ïºó±ã»á´ÓÕ»¶¥ÒƳý£¬Õâʱ¿ØÖÆÁ÷ÖØÐ»ص½ÁËbÖУ¬bÖ´ÐÐÍê±ÏͬÑùÒ²»á´ÓÕ»¶¥ÒƳý£¬×îºó¿ØÖÆÁ÷Óֻص½ÁËaÖУ¬×îºóaÖ´ÐÐÍê±Ï£¬aÒ²´Ó¶ÑÕ»ÖÐÒÆ³ý¡£

ÎÒÃÇ¿ÉÒÔÀûÓÃconsole.trace()À´¸üºÃµÄÑÝʾÕâÖÖÐÐΪ£¬Ëü»áÔÚ¿ØÖÆÌ¨´òÓ¡³öµ±Ç°¶ÑÕ»ÖеļǼ¡£´ËÍ⣬ͨ³£¶øÑÔÄãÓ¦¸Ã´ÓÉϵ½Ï¶ÁÈ¡¶ÑÕ»¼Ç¼¡£ÏëÏëÏÂÃæµÄÿһÐдúÂë¶¼ÊÇÔÚÄĵ÷Óõġ£

function c() {
console.log('c');
console.trace();
}

function b() {
console.log('b');
c();
}

function a() {
console.log('a');
b();
}

a();

ÔÚNode REPL·þÎñÆ÷ÉÏÔËÐÐÉÏÊö´úÂë»áµÃµ½ÈçϽá¹û£º

Trace  
at c (repl:3:9)
at b (repl:3:1)
at a (repl:3:1)
at repl:1:1 // <-- For now feel free to ignore anything below this point, these are Node's internals
at realRunInThisContextScript (vm.js:22:35)
at sigintHandlersWrap (vm.js:98:12)
at ContextifyScript.Script.runInThisContext (vm.js:24:12)
at REPLServer.defaultEval (repl.js:313:29)
at bound (domain.js:280:14)
at REPLServer.runBound [as eval] (domain.js:293:12)

ÈçÄãËù¼û£¬µ±ÎÒÃÇÔÚcÖдòÓ¡¶ÑÕ»£¬¶ÑÕ»ÖеļǼΪa,b,c¡£

Èç¹ûÎÒÃÇÏÖÔÚÔÚbÖв¢ÇÒÔÚcÖ´ÐÐÍêÖ®ºó´òÓ¡¶ÑÕ»£¬ÎÒÃǽ«»á·¢ÏÖcÒѾ­´Ó¶ÑÕ»µÄ¶¥²¿ÒƳý£¬Ö»Ê£ÏÂÁËaºÍb¡£

function c() {
console.log('c');
}

function b() {
console.log('b');
c();
console.trace();
}

function a() {
console.log('a');
b();
}

a();

ÕýÈçÄã¿´µ½µÄÄÇÑù£¬¶ÑÕ»ÖÐÒѾ­Ã»ÓÐc£¬ÒòΪËüÒѾ­Íê³ÉÔËÐУ¬ÒѾ­±»µ¯³öÈ¥ÁË¡£

Trace
at b (repl:4:9)
at a (repl:3:1)
at repl:1:1 // <-- For now feel free to ignore anything below this point, these are Node's internals
at realRunInThisContextScript (vm.js:22:35)
at sigintHandlersWrap (vm.js:98:12)
at ContextifyScript.Script.runInThisContext (vm.js:24:12)
at REPLServer.defaultEval (repl.js:313:29)
at bound (domain.js:280:14)
at REPLServer.runBound [as eval] (domain.js:293:12)
at REPLServer.onLine (repl.js:513:10)

×ܽ᣺µ÷Ó÷½·¨£¬·½·¨±ã»áÌí¼Óµ½¶ÑÕ»¶¥²¿£¬Ö´ÐÐÍê±ÏÖ®ºó£¬Ëü¾Í»á´Ó¶ÑÕ»Öе¯³ö¡£

Error¶ÔÏó ºÍ Error´¦Àí

µ±³ÌÐò·¢Éú´íÎóʱ£¬Í¨³£¶¼»áÅ׳öÒ»¸öError¶ÔÏó¡£Error¶ÔÏóÒ²¿ÉÒÔ×÷Ϊһ¸öÔ­ÐÍ£¬Óû§¿ÉÒÔÀ©Õ¹Ëü²¢´´½¨×Ô¶¨Òå´íÎó¡£

Error.prototype¶ÔÏóͨ³£ÓÐÒÔÏÂÊôÐÔ£º

1.constructor- ʵÀýÔ­Ð͵Ĺ¹Ô캯Êý¡£

2.message - ´íÎóÐÅÏ¢

3.name - ´íÎóÃû³Æ

ÒÔÉ϶¼ÊDZê×¼ÊôÐÔ£¬£¨µ«£©ÓÐʱºòÿ¸ö»·¾³¶¼ÓÐÆäÌØ¶¨µÄÊôÐÔ£¬ÔÚÀýÈçNode£¬Firefox£¬Chorme£¬Edge£¬IE 10+£¬Opera ºÍ Safari 6+ ÖУ¬»¹ÓÐÒ»¸ö°üº¬´íÎó¶ÑÕ»¼Ç¼µÄstackÊôÐÔ¡£´íÎó¶ÑÕ»¼Ç¼°üº¬´Ó£¨¶ÑÕ»µ×²¿£©Ëü×Ô¼ºµÄ¹¹Ô캯Êýµ½£¨¶ÑÕ»¶¥²¿£©ËùÓеĶÑÕ»Ö¡¡£

Èç¹ûÏëÁ˽â¸ü¶à¹ØÓÚError¶ÔÏóµÄ¾ßÌåÊôÐÔ£¬ÎÒÇ¿ÁÒÍÆ¼öMDNÉϵÄÕâÆªÎÄÕ¡£

Å׳ö´íÎó±ØÐëʹÓÃthrow¹Ø¼ü×Ö£¬Äã±ØÐ뽫¿ÉÄÜÅ׳ö´íÎóµÄ´úÂë°ü¹üÔÚtry´úÂë¿éÄÚ²¢½ô¸ú×ÅÒ»¸öcatch´úÂë¿éÀ´²¶»ñÅ׳öµÄ´íÎó¡£

ÕýÈçJavaÖеĴíÎó´¦Àí,try/catch´úÂë¿éºó½ô¸ú×ÅÒ»¸öfinally´úÂë¿éÔÚJavaScriptÖÐÒ²ÊÇͬÑùÔÊÐíµÄ£¬ÎÞÂÛtry´úÂë¿éÄÚÊÇ·ñÅ׳öÒì³££¬finally´úÂë¿éÄڵĴúÂë¶¼»áÖ´ÐС£ÔÚÍê³É´¦ÀíÖ®ºó£¬×î¼Ñʵ¼ùÊÇÔÚfinally´úÂë¿éÖÐ×öһЩÇåÀíµÄÊÂÇ飬(ÒòΪ)ÎÞÂÛÄãµÄ²Ù×÷ÊÇ·ñÉúЧ£¬¶¼²»»áÓ°Ïìµ½ËüµÄÖ´ÐС£

(¼øÓÚ)ÉÏÃæËù̸µ½µÄËùÓÐÊÂÇé¶Ô´ó¶àÊýÈËÀ´½²¶¼ÊÇС²ËÒ»µú£¬ÄÇô¾ÍÈÃÎÒÃÇÀ´Ì¸Ò»Ð©²»ÎªÈËËùÖªµÄϸ½Ú¡£

try´úÂë¿éºóÃæ²»±Ø½ô¸ú×Åcatch,µ«(´ËÖÖÇé¿öÏÂ)Æäºó±ØÐë½ô¸ú×Åfinally¡£ÕâÒâζ×ÅÎÒÃÇ¿ÉÒÔʹÓÃÈýÖÖ²»Í¬ÐÎʽµÄtryÓï¾ä£º

try...catch

try...finally

try...catch...finally

TryÓï¾ä¿ÉÒÔÏñÏÂÃæÕâÑù»¥ÏàǶÌ×£º

try {
try {
throw new Error('Nested error.'); // The error thrown here will be caught by its own `catch` clause
} catch (nestedErr) {
console.log('Nested catch'); // This runs
}
} catch (err) {
console.log('This will not run.');
}

ÄãÉõÖÁ»¹¿ÉÒÔÔÚcatchºÍfinally´úÂë¿éÖÐǶÌ×tryÓï¾ä£º

try {
throw new Error('First error');
} catch (err) {
console.log('First catch running');
try {
throw new Error('Second error');
} catch (nestedErr) {
console.log('Second catch running.');
}
}

try {
console.log('The try block is running...');
} finally {
try {
throw new Error('Error inside finally.');
} catch (err) {
console.log('Caught an error inside the finally block.');
}
}

»¹ÓкÜÖØÒªµÄÒ»µãÖµµÃ×¢Ò⣬ÄǾÍÊÇÎÒÃÇÉõÖÁ¿ÉÒÔ´ó¿É²»±ØÅ׳öError¶ÔÏó¡£¾¡¹ÜÕâ¿´ÆðÀ´·Ç³£coolÇҷdz£×ÔÓÉ£¬µ«Êµ¼Ê²¢·ÇÈç´Ë£¬ÓÈÆäÊǶԿª·¢µÚÈý·½¿âµÄ¿ª·¢ÕßÀ´Ëµ£¬ÒòΪËûÃDZØÐë´¦ÀíÓû§(ʹÓÿâµÄ¿ª·¢Õß)µÄ´úÂë¡£ÓÉÓÚȱ·¦±ê×¼£¬ËûÃDz¢²»ÄܰѿØÓû§µÄÐÐΪ¡£Äã²»ÄÜÏàÐÅÓû§²¢¼òµ¥µÄÅ׳öÒ»¸öError¶ÔÏó£¬ÒòΪËûÃDz»Ò»¶¨»áÄÇô×ö¶øÊǽö½öÅ׳öÒ»¸ö×Ö·û´®»òÕßÊý×Ö(¹íÖªµÀÓû§»áÅ׳öʲô)¡£ÕâҲʹµÃ´¦Àí±ØÒªµÄ¶ÑÕ»¸ú×ÙºÍÆäËûÓÐÒâÒåµÄÔªÊý¾Ý±äµÃ¸ü¼ÓÀ§ÄÑ¡£

¼ÙÉèÓÐÒÔÏ´úÂ룺

function runWithoutThrowing(func) {
try {
func();
} catch (e) {
console.log('There was an error, but I will not throw it.');
console.log('The error\'s message was: ' + e.message)
}
}

function funcThatThrowsError() {
throw new TypeError('I am a TypeError.');
}

runWithoutThrowing(funcThatThrowsError);

Èç¹ûÄãµÄÓû§ÏñÉÏÃæÕâÑù´«µÝÒ»¸öÅ׳öError¶ÔÏóµÄº¯Êý¸ørunWithoutThrowingº¯Êý(ÄǾÍлÌìлµØÁË)£¬È»¶ø×ÜÓÐЩÈË͵ÏëÀÁÖ±½ÓÅ׳öÒ»¸öString,ÄÇÄã¾ÍÂé·³ÁË£º

function runWithoutThrowing(func) {
try {
func();
} catch (e) {
console.log('There was an error, but I will not throw it.');
console.log('The error\'s message was: ' + e.message)
}
}

function funcThatThrowsString() {
throw 'I am a String.';
}

runWithoutThrowing(funcThatThrowsString);

ÏÖÔÚµÚ¶þ¸öconsole.log»á´òÓ¡³ö the error¡¯s message is undefined.Õâô¿´À´Ò²Ã»¶à´óµÄÊÂ(ºó¹û)ѽ£¬µ«ÊÇÈç¹ûÄúÐèҪȷ±£Ä³Ð©ÊôÐÔ´æÔÚÓÚError¶ÔÏóÉÏ£¬»òÒÔÁíÒ»ÖÖ·½Ê½£¨ÀýÈçChaiµÄthrows¶ÏÑÔ does)£©´¦ÀíError¶ÔÏóµÄÌØ¶¨ÊôÐÔ£¬ÄÇôÄã×öÐèÒª¸ü¶àµÄ¹¤×÷£¬ÒÔÈ·±£Ëü»áÕý³£¹¤×Ê¡£

´ËÍ⣬µ±Å׳öµÄÖµ²»ÊÇError¶ÔÏóʱ£¬ÄãÎÞ·¨·ÃÎÊÆäËûÖØÒªÊý¾Ý£¬ÀýÈçstack£¬ÔÚijЩ»·¾³ÖÐËüÊÇError¶ÔÏóµÄÒ»¸öÊôÐÔ¡£

ErrorsÒ²¿ÉÒÔÏñÆäËûÈκζÔÏóÒ»ÑùʹÓ㬲¢²»Ò»¶¨·ÇµÃÒªÅ׳öËûÃÇ£¬ÕâÒ²ÊÇËüÃÇΪʲô¶à´Î±»ÓÃ×÷»Øµ÷º¯ÊýµÄµÚÒ»¸ö²ÎÊý(Ë×³Æ err first)¡£ ÔÚÏÂÃæµÄfs.readdir()Àý×ÓÖоÍÊÇÕâôÓõġ£

const fs = require('fs');

fs.readdir('/example/i-do-not-exist', function callback(err, dirs) {
if (err instanceof Error) {
// `readdir` will throw an error because that directory does not exist
// We will now be able to use the error object passed by it in our callback function
console.log('Error Message: ' + err.message);
console.log('See? We can use Errors without using try statements.');
} else {
console.log(dirs);
}
});

×îºó£¬ÔÚrejecting promisesʱҲ¿ÉÒÔʹÓÃError¶ÔÏó¡£ÕâʹµÃËü¸üÈÝÒ×´¦Àípromise rejections£º

new Promise(function(resolve, reject) {
reject(new Error('The promise was rejected.'));
}).then(function() {
console.log('I am an error.');
}).catch(function(err) {
if (err instanceof Error) {
console.log('The promise was rejected with an error.');
console.log('Error Message: ' + err.message);
}
});

²Ù×ݶÑÕ»¸ú×Ù

ÉÏÃæ†ªàÂÁËÄÇô¶à£¬Ñ¹ÖáµÄÖØÍ·Ï·À´ÁË£¬ÄǾÍÊÇÈçºÎ²Ù×ݶÑÕ»¸ú×Ù¡£

±¾ÕÂרÃÅÕë¶ÔÄÇЩÏñNodeJSÖ§Error.captureStackTraceµÄ»·¾³¡£

Error.captureStackTraceº¯Êý½ÓÊÜÒ»¸öobject×÷ΪµÚÒ»¸ö²ÎÊý£¬µÚ¶þ¸ö²ÎÊýÊÇ¿ÉÑ¡µÄ£¬½ÓÊÜÒ»¸öº¯Êý¡£capture stack trace ²¶»ñµ±Ç°¶ÑÕ»¸ú×Ù£¬²¢ÔÚÄ¿±ê¶ÔÏóÖд´½¨Ò»¸östackÊôÐÔÀ´´æ´¢Ëü¡£Èç¹ûÌṩÁ˵ڶþ¸ö²ÎÊý£¬Ôò´«µÝµÄº¯Êý½«±»ÊÓΪµ÷ÓöÑÕ»µÄÖյ㣬Òò´Ë¶ÑÕ»¸ú×Ù½«½öÏÔʾµ÷Óøú¯Êý֮ǰ·¢ÉúµÄµ÷Óá£

ÈÃÎÒÃÇÓÃÀý×ÓÀ´ËµÃ÷ÕâÒ»µã¡£Ê×ÏÈ£¬ÎÒÃǽ«²¶»ñµ±Ç°¶ÑÕ»¸ú×Ù²¢½«Æä´æ´¢ÔÚ¹«¹²¶ÔÏóÖС£

const myObj = {};

function c() {
}

function b() {
// Here we will store the current stack trace into myObj
Error.captureStackTrace(myObj);
c();
}

function a() {
b();
}

// First we will call these functions
a();

// Now let's see what is the stack trace stored into myObj.stack
console.log(myObj.stack);

// This will print the following stack to the console:
// at b (repl:3:7) <-- Since it was called inside B, the B call is the last entry in the stack
// at a (repl:2:1)
// at repl:1:1 <-- Node internals below this line
// at realRunInThisContextScript (vm.js:22:35)
// at sigintHandlersWrap (vm.js:98:12)
// at ContextifyScript.Script.runInThisContext (vm.js:24:12)
// at REPLServer.defaultEval (repl.js:313:29)
// at bound (domain.js:280:14)
// at REPLServer.runBound [as eval] (domain.js:293:12)
// at REPLServer.onLine (repl.js:513:10)

²»ÖªµÀÄã×¢Ò⵽û£¬ÎÒÃÇÊ×Ïȵ÷ÓÃÁËa(aÈëÕ»)£¬È»ºóÎÒÃÇaÖÐÓÖµ÷ÓÃÁËb(bÈëÕ»ÇÒÔÚaÖ®ÉÏ)¡£È»ºóÔÚbÖÐÎÒÃDz¶»ñÁ˵±Ç°¶ÑÕ»¼Ç¼²¢½«Æä´æ´¢ÔÚmyObjÖС£Òò´ËÔÚ¿ØÖÆÌ¨ÖвŻᰴÕÕb aµÄ˳Ðò´òÓ¡¶ÑÕ»¡£

ÏÖÔÚÈÃÎÒÃǸøError.captureStackTrace´«µÝÒ»¸öº¯Êý×÷ΪµÚ¶þ¸ö²ÎÊý£¬¿´¿´»á·¢Éúʲô£º

const myObj = {};

function d() {
// Here we will store the current stack trace into myObj
// This time we will hide all the frames after `b` and `b` itself
Error.captureStackTrace(myObj, b);
}

function c() {
d();
}

function b() {
c();
}

function a() {
b();
}

// First we will call these functions
a();

// Now let's see what is the stack trace stored into myObj.stack
console.log(myObj.stack);

// This will print the following stack to the console:
// at a (repl:2:1) <-- As you can see here we only get frames before `b` was called
// at repl:1:1 <-- Node internals below this line
// at realRunInThisContextScript (vm.js:22:35)
// at sigintHandlersWrap (vm.js:98:12)
// at ContextifyScript.Script.runInThisContext (vm.js:24:12)
// at REPLServer.defaultEval (repl.js:313:29)
// at bound (domain.js:280:14)
// at REPLServer.runBound [as eval] (domain.js:293:12)
// at REPLServer.onLine (repl.js:513:10)
// at emitOne (events.js:101:20)

µ±°Ñb´«¸øError.captureStackTraceFunctionʱ£¬ËüÒþ²ØÁËb±¾ÉíÒÔ¼°ËüÖ®ºóËùÓеĵ÷ÓÃÖ¡¡£Òò´Ë¿ØÖÆÌ¨½ö½ö´òÓ¡³öÒ»¸öa¡£

ÖÁ´ËÄãÓ¦¸Ã»áÎÊ×Ô¼º£º¡°Õâµ½µ×ÓÐʲôÓã¿¡±¡£Õâ·Ç³£ÓÐÓã¬ÒòΪÄã¿ÉÒÔÓÃËüÀ´Òþ²ØÓëÓû§Î޹صÄÄÚ²¿ÊµÏÖϸ½Ú¡£ÔÚChaiÖУ¬ÎÒÃÇʹÓÃËüÀ´±ÜÃâÏòÓû§ÏÔʾÎÒÃÇÊÇÈçºÎʵʩ¼ì²éºÍ¶ÏÑÔ±¾ÉíµÄ²»Ïà¹ØµÄϸ½Ú¡£

²Ù×÷¶ÑÕ»×·×Ùʵս

ÕýÈçÎÒÔÚÉÏÒ»½ÚÖÐÌáµ½µÄ£¬ChaiʹÓöÑÕ»²Ù×÷¼¼Êõʹ¶ÑÕ»¸ú×Ù¸ü¼ÓÓëÎÒÃǵÄÓû§Ïà¹Ø¡£ÏÂÃæ½«½ÒÏþÎÒÃÇÊÇÈçºÎ×öµ½µÄ¡£

Ê×ÏÈ£¬ÈÃÎÒÃÇÀ´¿´¿´µ±¶ÏÑÔʧ°ÜʱÅ׳öµÄAssertionErrorµÄ¹¹Ô캯Êý£º

// `ssfi` stands for 
"start stack function". It is the reference to the// starting point for removing irrelevant frames from the stack trace
function AssertionError (message, _props, ssf) {
var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON')
, props = extend(_props || {});

// Default values
this.message = message || 'Unspecified AssertionError';
this.showDiff = false;

// Copy from properties
for (var key in props) {
this[key] = props[key];
}

// Here is what is relevant for us:
// If a start stack function was provided we capture the current stack trace and pass
// it to the `captureStackTrace` function so we can remove frames that come after it
ssf = ssf || arguments.callee;
if (ssf && Error.captureStackTrace) {
Error.captureStackTrace(this, ssf);
} else {
// If no start stack function was provided we just use the original stack property
try {
throw new Error();
} catch(e) {
this.stack = e.stack;
}
}
}

ÈçÄãËù¼û£¬ÎÒÃÇʹÓÃError.captureStackTrace²¶»ñ¶ÑÕ»×·×Ù²¢½«Ëü´æ´¢ÔÚÎÒÃÇÕýÔÚ´´½¨µÄAssertErrorʵÀýÖУ¨Èç¹û´æÔڵϰ£©£¬È»ºóÎÒÃǽ«Ò»¸öÆðʼ¶ÑÕ»º¯Êý´«µÝ¸øËü£¬ÒÔ±ã´Ó¶ÑÕ»¸ú×ÙÖÐɾ³ý²»Ïà¹ØµÄµ÷ÓÃÖ¡£¬ËüÖ»ÏÔʾChaiµÄÄÚ²¿ÊµÏÖϸ½Ú£¬×îÖÕʹ¶ÑÕ»±äµÃÇåÎúÃ÷ÁË¡£

ÏÖÔÚÈÃÎÒÃÇÀ´¿´¿´@meeberÔÚÕâ¸öÁîÈ˾ªÌ¾µÄPRÖÐÌá½»µÄ´úÂë¡£

ÔÚÄ㿪ʼ¿´ÏÂÃæµÄ´úÂë֮ǰ£¬ÎÒ±ØÐë¸æËßÄãaddChainableMethod·½·¨ÊǸÉɶµÄ¡£Ëü½«´«µÝ¸øËüµÄÁ´Ê½·½·¨Ìí¼Óµ½¶ÏÑÔÉÏ£¬ËüÒ²Óðüº¬¶ÏÑԵķ½·¨±ê¼Ç¶ÏÑÔ±¾Éí£¬²¢½«Æä±£´æÔÚ±äÁ¿ssfi(Æô¶¯¶ÑÕ»º¯Êýָʾ·û)ÖС£ÕâÒ²¾ÍÒâζ×ŵ±Ç°¶ÏÑÔ½«»áÊǶÑÕ»ÖеÄ×îºóÒ»¸öµ÷ÓÃÖ¡£¬Òò´ËÎÒÃDz»»áÔÚ¶ÑÕ»ÖÐÏÔʾChaiÖеÄÈκνøÒ»²½µÄÄÚ²¿·½·¨¡£ÎÒûÓÐÌí¼ÓÕû¸ö´úÂ룬ÒòΪËü×öÁ˺ܶàÊÂÇ飬Óе㼬ÊÖ£¬µ«Èç¹ûÄãÏë¶ÁËü£¬µãÎÒÔĶÁ¡£

ÏÂÃæµÄÕâ¸ö´úÂëÆ¬¶ÎÖУ¬ÎÒÃÇÓÐÒ»¸ölengOf¶ÏÑÔµÄÂß¼­£¬Ëü¼ì²éÒ»¸ö¶ÔÏóÊÇ·ñÓÐÒ»¶¨µÄlength¡£ÎÒÃÇÏ£ÍûÓû§¿ÉÒÔÏñÕâÑùÀ´Ê¹ÓÃËü

function assertLength (n, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object')
, ssfi = flag(this, 'ssfi');

// Pay close attention to this line
new Assertion(obj, msg, ssfi, true).to.have.property('length');
var len = obj.length;

// This line is also relevant
this.assert(
len == n
, 'expected #{this} to have a length of #{exp} but got #{act}'
, 'expected #{this} to not have a length of #{act}'
, n
, len
);
}

Assertion.addChainableMethod('lengthOf', assertLength, assertLengthChain);

ÔÚÉÏÃæµÄ´úÂëÆ¬¶ÎÖУ¬ÎÒÍ»³öÇ¿µ÷ÁËÓëÎÒÃÇÏÖÔÚÏà¹ØµÄ´úÂë¡£ÈÃÎÒÃÇ´Óµ÷ÓÃthis.assert¿ªÊ¼ËµÆð¡£

ÒÔÏÂÊÇthis.assert·½·¨µÄÔ´´úÂ룺

Assertion.prototype.assert
= function (expr, msg, negateMsg, expected, _actual, showDiff) { var ok = util.test(this, arguments);
if (false !== showDiff) showDiff = true;
if (undefined === expected && undefined === _actual) showDiff = false;
if (true !== config.showDiff) showDiff = false;

if (!ok) {
msg = util.getMessage(this, arguments);
var actual = util.getActual(this, arguments);

// This is the relevant line for us
throw new AssertionError(msg, {
actual: actual
, expected: expected
, showDiff: showDiff
}, (config.includeStack) ? this.assert : flag(this, 'ssfi'));
}
};

assert·½·¨¸ºÔð¼ì²é¶ÏÑÔ²¼¶û±í´ïʽÊÇ·ñͨ¹ý¡£Èç¹û²»Í¨¹ý£¬ÎÒÃÇÔòʵÀý»¯Ò»¸öAssertionError¡£²»ÖªµÀÄã×¢Ò⵽û£¬ÔÚʵÀý»¯AssertionErrorʱ£¬ÎÒÃÇÒ²¸øËü´«µÝÁËÒ»¸ö¶ÑÕ»×·×Ùº¯ÊýָʾÆ÷(ssfi)£¬Èç¹ûÅäÖõÄincludeStack´¦ÓÚ¿ªÆô״̬£¬ÎÒÃÇͨ¹ý½«this.assert±¾Éí´«µÝ¸øËüÀ´ÎªÓû§ÏÔʾÕû¸ö¶ÑÕ»¸ú×Ù¡£·´Ö®£¬ÎÒÃÇÔòÖ»ÏÔʾssfi±ê¼ÇÖд洢µÄÄÚÈÝ£¬Òþ²Øµô¶ÑÕ»¸ú×ÙÖиü¶àµÄÄÚ²¿ÊµÏÖϸ½Ú¡£

ÏÖÔÚÈÃÎÒÃÇÀ´ÌÖÂÛÏÂÒ»ÐкÍÎÒÃÇÏà¹ØµÄ´úÂë°É£º

`new Assertion
(obj, msg, ssfi, true).to.have.property('length');`

As you can see here we are passing the content we¡¯ve got from the ssfi flag when creating our nested assertion. This means that when the new assertion gets created it will use this function as the starting point for removing unuseful frames from the stack trace. By the way, this is the Assertion constructor: ÈçÄãËù¼û£¬ÎÒÃÇÔÚ´´½¨Ç¶Ì×¶ÏÑÔʱ½«´Óssfi±ê¼ÇÖеÄÄÚÈÝ´«µÝ¸øÁËËü¡£ÕâÒâζ×Åд´½¨µÄ¶ÏÑÔ»áʹÓÃÄǸö·½·¨×÷ΪÆðʼµ÷ÓÃÖ¡£¬´Ó¶ø¿ÉÒÔ´Ó¶ÑÕ»×·×ÙÖÐÇå³ýûÓеĵ÷ÓÃÕ»¡£Ë³±ãÒ²¿´ÏÂAssertionµÄ¹¹ÔìÆ÷°É£º

function Assertion (obj, msg, ssfi, lockSsfi) {
// This is the line that matters to us
flag(this, 'ssfi', ssfi || Assertion);
flag(this, 'lockSsfi', lockSsfi);
flag(this, 'object', obj);
flag(this, 'message', msg);

return util.proxify(this);
}

²»ÖªµÀÄãÊÇ·ñ»¹¼ÇµÄÎÒÏÈǰ˵¹ýµÄaddChainableMethod·½·¨£¬ËüʹÓÃ×Ô¼ºµÄ¸¸¼¶·½·¨ÉèÖÃssfi±êÖ¾£¬ÕâÒâζ×ÅËüʼÖÕ´¦ÓÚ¶ÑÕ»µÄµ×²¿£¬ÎÒÃÇ¿ÉÒÔɾ³ýËüÖ®ÉϵÄËùÓе÷ÓÃÖ¡¡£

ͨ¹ý½«ssfi´«µÝ¸øÇ¶Ì×¶ÏÑÔ£¬ËüÖ»¼ì²éÎÒÃǵĶÔÏóÊÇ·ñ¾ßÓ㤶ÈÊôÐÔ£¬ÎÒÃǾͿÉÒÔ±ÜÃâÖØÖÃÎÒÃǽ«ÒªÓÃ×÷Æðʼָ±êÆ÷µÄµ÷ÓÃÖ¡£¬È»ºóÔÚ¶ÑÕ»ÖпÉÒÔ¿´µ½ÒÔǰµÄaddChainableMethod¡£

Õâ¿ÉÄÜ¿´ÆðÀ´Óе㸴ÔÓ£¬ËùÒÔÈÃÎÒÃǻعËÒ»ÏÂÎÒÃÇÏë´ÓÕ»ÖÐɾ³ýÎÞÓõĵ÷ÓÃ֡ʱChaiÖÐËù·¢ÉúµÄÊÂÇ飺

µ±ÎÒÃÇÔËÐжÏÑÔʱ£¬ÎÒÃǽ«Ëü×Ô¼ºµÄ·½·¨×÷ÎªÒÆ³ý¶ÑÕ»ÖеÄÏÂÒ»¸öµ÷ÓÃÖ¡µÄ²Î¿¼

¶ÏÑÔʧ°Üʱ£¬ÎÒÃÇ»áÒÆ³ýËùÓÐÎÒÃÇÔڲο¼Ö¡Ö®ºó±£´æµÄÄÚ²¿µ÷ÓÃÖ¡¡£

Èç¹û´æÔÚǶÌ׵ĶÏÑÔ¡£ÎÒÃDZØÐëÒÀ¾ÉʹÓõ±Ç°¶ÏÑԵĸ¸·½·¨×÷Ϊɾ³ýÏÂÒ»¸öµ÷ÓÃÖ¡µÄ²Î¿¼µã£¬Òò´ËÎÒÃǰѵ±Ç°µÄssfi£¨Æðʼº¯ÊýָʾÆ÷£©´«µÝ¸øÎÒÃÇËù´´½¨µÄ¶ÏÑÔ£¬ÒÔ±ãËü¿ÉÒÔ±£´æ¡£

 

   
2105 ´Îä¯ÀÀ       27
Ïà¹ØÎÄÕÂ

Éî¶È½âÎö£ºÇåÀíÀôúÂë
ÈçºÎ±àд³öÓµ±§±ä»¯µÄ´úÂë
ÖØ¹¹-ʹ´úÂë¸ü¼ò½àÓÅÃÀ
ÍŶÓÏîÄ¿¿ª·¢"±àÂë¹æ·¶"ϵÁÐÎÄÕÂ
Ïà¹ØÎĵµ

ÖØ¹¹-¸ÄÉÆ¼ÈÓдúÂëµÄÉè¼Æ
Èí¼þÖØ¹¹v2
´úÂëÕû½àÖ®µÀ
¸ßÖÊÁ¿±à³Ì¹æ·¶
Ïà¹Ø¿Î³Ì

»ùÓÚHTML5¿Í»§¶Ë¡¢Web¶ËµÄÓ¦Óÿª·¢
HTML 5+CSS ¿ª·¢
ǶÈëʽC¸ßÖÊÁ¿±à³Ì
C++¸ß¼¶±à³Ì