เคล็ดลับสำหรับการเล่นกอล์ฟใน JavaScript


133

คุณมีเคล็ดลับทั่วไปเกี่ยวกับการเล่นกอล์ฟใน JavaScript หรือไม่ ฉันกำลังมองหาความคิดที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟโดยทั่วไปซึ่งอย่างน้อยค่อนข้างเฉพาะกับ JavaScript (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ)

หมายเหตุ:โปรดดูเคล็ดลับสำหรับการเล่นกอล์ฟใน ECMAScript 6 ขึ้นไป


ฉันสงสัยจริงๆว่ามันอนุญาตให้วางตัวแปรในระดับโลกvarหรือไม่? และรหัสกอล์ฟ JavaScript ควรเป็นฟังก์ชั่นหรือส่งออกบางสิ่งบางอย่างโดยตรง? ฉันคิดอย่างจริงใจว่านี่สามารถสร้างความแตกต่างได้มาก
pimvdb

1
@primvdb: มันได้รับอนุญาต แต่คุณต้องระวังเพราะมันอาจทำให้เกิดผลข้างเคียงถ้าฟังก์ชั่นถูกเรียกหลายครั้งและมันกำลังจัดการกับตัวแปรทั่วโลกหรือถ้ามันเป็นฟังก์ชั่นวนซ้ำ
mellamokb

คำตอบ:


108

แฟนซีสำหรับลูป

คุณสามารถใช้มาตรฐานสำหรับวงในวิธีที่ไม่ได้มาตรฐาน

for ( a; b; c )

โดยพื้นฐานแล้วเทียบเท่ากับ:

a;
while ( b )
{
  ...
  c;
}

ดังนั้นเคล็ดลับที่ดีคือการเขียนโค้ดของคุณด้วยการwhileวนซ้ำแล้วแยกมันออกเป็นa,b,cส่วนต่าง ๆ ในการforวนซ้ำ

ตัวอย่างที่ฉันเขียน :

for(x=y=n;!z;x--,y++)z=i(x)?x:i(y)?y:0
for(a=b=1;b<n;c=a+b,a=b,b=c);

เชนหมาของคุณ

หากคุณกำลังเริ่มต้นหรือรีเซ็ตค่าหลายค่าเชื่อมโยงค่ากับตัวแปรทั้งหมดที่ต้องการ:

a=b=1;

การหล่อโดยนัย

อย่าตรวจสอบประเภทของคุณเพียงใช้มันอย่างที่เป็น ตัวละครparseInt()ค่าใช้จ่าย 10หากคุณจำเป็นต้องใช้สตริงให้สร้างสรรค์:

a='30';
b='10';
c = a + b; //failure
c = parseInt(a) + parseInt(b) //too long

c = -(-a-b); //try these
c = ~~a+~~b;
c = +a+ +b;
c = a- -b;

หลีกเลี่ยงอัฒภาค

JavaScript มีการแทรกเครื่องหมายโคลอนอัตโนมัติ ใช้บ่อยและดี

หนึ่งสมุทร

บันทึกในวงเล็บด้วยการเลื่อนให้มากที่สุดเท่าที่ทำได้ในบรรทัดเดียวหรือพารามิเตอร์:

a( realParam1, realParam2, fizz='buzz' )

ผู้ประกอบการเพิ่ม / ลดลง

a = a - 1;
foo(a);

และ

foo(a);
a = a - 1;

สามารถเขียนใหม่ได้อย่างง่ายดายเช่น

foo(--a);

และ

foo(a--);

ตามลำดับ

ใช้thisหรือselfแทนwindowบริบททั่วโลก

อธิบายการประหยัดตัวละครด้วยตนเอง 2 ครั้ง

ใช้เครื่องหมายวงเล็บสำหรับการเข้าถึงคุณสมบัติซ้ำ

นี่เป็นการกระทำที่สมดุลระหว่างความยาวชื่อคุณสมบัติและจำนวนการเข้าถึง แทนที่จะบันทึกa.longFunctionName()ด้วยเครื่องหมายจุดสองครั้งจะสั้นกว่าในการบันทึกชื่อและเรียกใช้ฟังก์ชันผ่านเครื่องหมายวงเล็บ:

a.longFunctionName(b)
a.longFunctionName(c)
//42

-vs-

a[f='longFunctionName'](b)
a[f](c)
//34

สิ่งนี้มีประสิทธิภาพเป็นพิเศษด้วยฟังก์ชั่นdocument.getElementByIdที่สามารถลดd[e]ขนาด

บันทึก:

ด้วยเครื่องหมายวงเล็บค่าใช้จ่ายจะเป็น6 + name.lengthอักขระในครั้งแรก การเข้าถึงแต่ละครั้งที่ตามมามีค่าใช้จ่ายของ3ตัวละคร

สำหรับเครื่องหมายจุดทั้งหมดจะเข้าถึงค่าใช้จ่ายname.length + 1(+1 สำหรับ.ตัวอักษร)

6 + name.length + (3 * (accesses - 1)) < accesses * (name.length + 1)ใช้วิธีนี้ถ้า

len = ความยาวของชื่อคุณสมบัติ
i = การเข้าถึงขั้นต่ำเพื่อใช้ประโยชน์

len | i 
========
1   |  
2   |  
3   | 7 
4   | 4 
5   | 3 
6   | 3 
7   | 3 
8+  | 2 

จำนวนการเข้าถึงสามารถขยายหลายวัตถุ หากคุณเข้าถึง.length4 'length'ครั้งหรือมากกว่าในอาร์เรย์ที่แตกต่างกันคุณสามารถใช้ตัวแปรเดียวกันถือสตริง


5
c = ~~a-~~bc = ~~a+~~bควรจะเป็น นอกจากนี้คุณสามารถโยนโดยปริยายจำนวนเต็มโดยใช้ตัวอย่างเช่น|0 Math.random()*6|0
mellamokb

7
มันถูกกว่าการบีบบังคับสตริงให้เป็นตัวเลขด้วยตัวดำเนินการบวก หากaและbเป็นสตริงคุณสามารถทำการ+a+bแปลงเป็นตัวเลขและเพิ่มได้
Peter Olson

8
ฉันสาบานว่าฉันจะใช้d- -bรหัสของฉันในสักวันหนึ่ง ...
John Dvorak

4
+ a + b ไม่ทำงาน (อย่างน้อยในเหมือง ... ) // a = "1", b = "1", + a + b // ให้ "11"
imma

2
สำหรับ "ใช้ Array-Access สำหรับการเรียกใช้ฟังก์ชั่นซ้ำ" หากคุณใช้ฟังก์ชันมากกว่าสองครั้งบนวัตถุเดียวกันสิ่งที่สั้นกว่าเล็กน้อยคือการกำหนดฟังก์ชั่นให้กับสมาชิกใหม่เช่นa.f=a.longfunctionname;a.f(b);a.f(c);a.f(d)
Martin Ender

131

แยกด้วยตัวเลขเพื่อบันทึกคำพูด:

"alpha,bravo,charlie".split(",") // before
"alpha0bravo0charlie".split(0)   // after

2
มันใช้งานได้และฉันใช้มันเป็นตัวเลขหลายหลัก
Isiah Meadows

12
ฮ่า ๆ นี่เป็นความคิดสร้างสรรค์ที่น่ารักจริงๆ
NiCk Newman

9
ใน ES6 สิ่งนี้ไม่สำคัญอีกต่อไปคุณสามารถทำได้.split`...`
David Archibald

"alpha,bravo,charlie".split`,`
Kamil Kiełczewski

56

ใช้เครื่องหมายจุลภาคเพื่อหลีกเลี่ยงการจัดฟัน ( ใช้กับ C ) ด้วย:

if(i<10)m+=5,n-=3;

แทน

if(i<10){m+=5;n-=3}

ซึ่งมีความยาวหนึ่งตัวอักษร


2
เครื่องหมายอัฒภาคจำเป็นเมื่อสิ้นสุดตัวอย่างแรกหรือไม่
wjl

4
@wjlafrance: มันจะไม่ถูกต้องเฉพาะในตอนท้ายของสายการบินเดียว
mellamokb

48

การสร้างหมายเลขแบบสุ่มสั้นลง

หากคุณต้องการบูลีนแบบสุ่ม ( 0หรือ1):

new Date&1 // equivalent to Math.random()<0.5

หากคุณต้องการจำนวนเต็มแบบสุ่ม0 <= n < 1337:

new Date%1337 // equivalent to Math.floor(Math.random()*1337))

วิธีนี้ใช้งานได้เนื่องจาก a Dateถูกเก็บไว้ภายใน JavaScript เป็นจำนวนมิลลิวินาทีนับตั้งแต่ยุคดังนั้นค่าnew Dateจะถูกรวมเข้าด้วยกัน123somebignumber456เมื่อคุณพยายามทำเลขจำนวนเต็มกับมัน

แน่นอนว่าตัวเลข "สุ่ม" เหล่านี้จะไม่สุ่มโดยเฉพาะถ้าคุณโทรหาพวกเขาหลายครั้งติดต่อกันอย่างรวดเร็วดังนั้นโปรดจำไว้


1
เพิ่งจำคำตอบนี้ในขณะที่อ่านโปรแกรมเมอร์ผู้หลอกลวงเพิ่มเติมเชื่อเกี่ยวกับเวลา : “ 21. หากคุณสร้างวัตถุวันที่สองวัตถุที่อยู่ติดกันวัตถุเหล่านั้นจะแสดงในเวลาเดียวกัน (กำเนิด Heisenbug ยอดเยี่ยม)”
Sebastian Simon

39

คุณสามารถใช้วัตถุรูปแบบของตัวอักษรได้รับ / functionชุดเพื่อหลีกเลี่ยงการใช้คำว่า

var obj = {
  get f(){
    console.log("just accessing this variable runs this code");
    return "this is actually a function";
  },
  set f(v){
    console.log("you can do whatever you want in here, passed: " + v);
  }
};

1 && obj.f; // runs obj.[[get f]]
obj.f = Infinity; // runs obj.[[set f]](Infinity)

ส่วน getter / setter นั้นมีประโยชน์จริงๆ ขอบคุณ
gion_13

1
ที่จริงยิ่งกว่านั้นคือวิธีการของวัตถุถ้าคุณใช้มัน <= 2 ครั้งเท่านั้น ในทางกลับกันฟังก์ชั่นลูกศรนั้นดีกว่าในการตัดตัวอักษรเนื่องจากมันใช้งานได้เกือบเพื่อจุดประสงค์เดียวกันและคลาสก็ไม่ค่อยมีประโยชน์ในโค้ดกอล์ฟ
Isiah Meadows

หากการสนับสนุนเป็นสิ่งสำคัญฟังก์ชั่นลูกศรไม่ได้รับการสนับสนุนใน fx ie11
Jim Wolff

35

อันนี้ไม่ค่อยมีคนรู้จักและใช้น้อย แต่น่าประทับใจถ้าใช้ในสถานการณ์ที่ถูกต้อง พิจารณาฟังก์ชั่นที่ไม่มีการโต้แย้งและคืนค่าตัวเลขที่ต่างกันเสมอเมื่อถูกเรียกและหมายเลขที่ส่งคืนจะถูกใช้ในการคำนวณ:

var a = [ 
    Math.random()*12|0,
    Math.random()*11|0,
    Math.random()*10|0,
    /* etc... */ 
];

ตามปกติคุณอาจทำให้ฟังก์ชันนี้สั้นลงโดยใช้ชื่อตัวแปรตัวอักษร:

var r=Math.random,a=[r()*12|0,r()*11|0,r()*10|0,r()*9|0,r()*8|0,r()*7|0,r()*6|0,r()*5|0];

วิธีที่ดีกว่าในการลดความยาวคือการใช้valueOfงานที่ไม่เหมาะสมซึ่งจะช่วยให้คุณประหยัด 2 อักขระต่อการเรียกใช้ มีประโยชน์ถ้าคุณเรียกใช้ฟังก์ชันมากกว่า 5 ครั้ง:

var r={valueOf:Math.random},a=[r*12|0,r*11|0,r*10|0,r*9|0r*8|0,r*7|0,r*6|0,r*5|0];

8
หรือคุณสามารถทำได้เช่นนี้let a=[5,6,7,8,9,10,11,12].map(x=>x*Math.random()|0)หรือบันทึกlet a=Array(7).map((_,i)=>i*Math.random()|0+5)36 หรือ 42 ไบต์ตามลำดับ
Isiah Meadows

เป็นไปได้ที่จะเปลี่ยนr()หรือทำให้สั้นลง?
NiCk Newman

3
r={valueOf:Math.random}นั่นเป็นเพียงอัจฉริยะ: D
ETHproductions

1
@ Isiah ใช่คุณสามารถทำได้ตอนนี้ :
Andy E

32

การใช้ประโยชน์จากผู้ประกอบการลัดวงจร

แทนที่จะใช้ifข้อความที่ยาวหรือใช้ตัวดำเนินการที่สามคุณสามารถใช้&&และ||ย่อรหัสของคุณได้ ตัวอย่างเช่น

var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);

return match ? decodeURIComponent(match[1].replace(/\+/g, ' ')) : null;

สามารถกลายเป็น

var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);

return match && decodeURIComponent(match[1].replace(/\+/g, ' '));

||ผู้ประกอบการมักจะใช้วิธีนี้ในการตั้งค่าเริ่มต้น:

evt = evt || window.event;

นี่เป็นเหมือนกับการเขียน

if (!evt)
    evt = window.event;

การสร้างสตริงซ้ำโดยใช้Array

หากคุณต้องการเริ่มต้นสตริงที่ยาวของอักขระเฉพาะคุณสามารถทำได้โดยสร้างอาร์เรย์ที่มีความยาวn + 1โดยที่nคือจำนวนครั้งที่คุณต้องการทำซ้ำอักขระ:

// Create a string with 30 spaces
str = "                              ";

// or
str = Array(31).join(" ");

ยิ่งสตริงยิ่งใหญ่ก็ยิ่งประหยัดได้มากขึ้น

แยกตัวเลข

ใช้+และ~โอเปอเรเตอร์แทนparseFloat()หรือparseInt()เมื่อรวมชนิดสตริงที่เป็นตัวเลขกับชนิดตัวเลข:

var num = "12.6";
parseFloat(num) === +num;  // + is 10 characters shorter than parseFloat()

var num2 = "12"
parseInt(num2) === +num2;   // + is 8 characters shorter than parseInt()

var num3 = "12.6"
parseInt(num3) === ~~num3;  // ~~ is 7 characters shorter than parseInt()

var num4 = "12.6"
parseInt(num4) === num4|0;  // |0 is 7 characters shorter than parseInt()

ระวัง แต่ประเภทอื่น ๆ ที่สามารถรวมตัวกันกับผู้ประกอบการเหล่านี้ (เช่นtrueจะกลายเป็น1) 0สตริงที่ว่างเปล่าหรือสตริงที่มีพื้นที่สีขาวเพียงจะกลายเป็น อย่างไรก็ตามสิ่งนี้อาจมีประโยชน์ในบางสถานการณ์


6
+1 สำหรับการสร้างสตริงซ้ำโดยใช้ Array - ไม่เคยคิดมาก่อน
mellamokb

4
เพื่อสร้างสตริงซ้ำใน ES6 คุณสามารถใช้str.repeat(count)
Oriol

26

แอบเริ่มต้นตัวแปรในการโทรพร้อมท์ () สำหรับการรับผู้ใช้

n=prompt(i=5);     // sets i=5 at the same time as getting user input

แทนการใช้

n=prompt();i=5;

ในฐานะที่เป็นผลข้างเคียงมันจะแสดงค่าอินพุตในหน้าต่างพรอมต์ขณะที่บันทึก 1 อักขระ


12
สามารถใช้กับฟังก์ชันใด ๆ ที่ไม่ยอมรับอาร์กิวเมนต์ได้
Casey Chu

3
แม้ว่าฟังก์ชั่นจะยอมรับอาร์กิวเมนต์มันก็มีประโยชน์เช่นเดียวกับ[1,2,3].join('',i=5)ในกรณีที่มันบันทึกคู่ของเครื่องหมายปีกกา
DocMax

3
@DocMax: คุณสามารถใช้ประกอบการจุลภาคที่ i=5,[1,2,3].join()-
Konrad Borowski

@GlitchMr: ฉันทำได้ แต่ไม่ได้บันทึกอักขระใด ๆ ฉันยอมรับว่าส่วนใหญ่เวลาที่จะสะอาด ฉันคิดว่าอาจยังมีบางกรณีที่การสั่งซื้อของฉันอาจประหยัดถ่านแม้ว่าฉันจะไม่สามารถหาซื้อได้ในขณะนี้ (และฉันอาจผิด)
DocMax

@DocMax เฉพาะในกรณีที่คุณใช้ประโยชน์จาก ASI
Isiah Meadows

24

รวมซ้อนกันสำหรับลูป:

// before:
for(i=5;i--;)for(j=5;j--;)dosomething(i,j)

// after:
for(i=25;i--;)dosomething(0|i/5,i%5)

ตัวอย่างที่มีค่าต่างกันสำหรับi/ j:

// before:
for(i=4;i--;)for(j=7;j--;)dosomething(i,j)

// after:
for(i=28;i--;)dosomething(0|i/7,i%7)

(ฉันแก้ไขก) พิมพ์ผิดเล็กน้อย แต่ฉลาดมาก! โปรดทราบว่านี่จะใช้งานได้กับลูปที่ซ้อนกันที่มีความยาวเท่ากัน (ยกเว้นว่าฉันผิด)
Camilo Martin

1
@CamiloMartin ไม่ลูปไม่จำเป็นต้องมีความยาวเท่ากัน จำนวนที่เกิดจากการทำซ้ำเป็นi*jและผู้ประกอบการส่วน / โมดูลัสเรียกค่าส่วนบุคคลของและi j
quietmint

@ user113215 คุณพูดถูกน่ากลัว! :) ฉันได้แก้ไขคำตอบเพื่อรวมตัวอย่าง
Camilo Martin

23

ทางลัด Unicode

หากคุณใช้ทรัพย์สินที่มีอยู่ในตัวในการแข่งขันกอล์ฟที่ยิ่งใหญ่คุณสามารถใช้นามแฝงของอสังหาริมทรัพย์ทุกประเภทเทียบเท่าตัวละครตัวหนึ่ง:

[Math,Number,S=String,Array].map(b=>
    Object.getOwnPropertyNames(b).map((p,i)=>
        b.prototype[S.fromCharCode(i+248)]=b[p]
    )
)

หลังจากรันโค้ดข้างต้นคุณสามารถใช้มันเช่นนี้:
"foo".Č(/.*/,'bar') // replaces foo with bar

ค่าใช้จ่ายนี้ 118 ไบต์ดังนั้นจึงอาจไม่มีประโยชน์ในบางสถานการณ์

มันอาจจะขึ้นอยู่กับเบราว์เซอร์และฉันไม่แน่ใจว่ามันสั้นกว่าwith(Array){join(foo),...}หรือกำหนดตัวแปรเป็นคุณสมบัติที่ใช้with(Array){j=join,m=map...}แต่ก็ยังเป็นสิ่งที่ควรค่าแก่การกล่าวถึง

    Math        Number              String              Array

ø   toSource    prototype           prototype           prototype
ù   abs         NaN                 quote               join
ú   acos        POSITIVE_INFINITY   substring           reverse
û   asin        NEGATIVE_INFINITY   toLowerCase         sort
ü   atan        MAX_VALUE           toUpperCase         push
ý   atan2       MIN_VALUE           charAt              pop
þ   ceil        MAX_SAFE_INTEGER    charCodeAt          shift
ÿ   clz32       MIN_SAFE_INTEGER    contains            unshift
Ā   cos         EPSILON             indexOf             splice
ā   exp         isFinite            lastIndexOf         concat
Ă   floor       isInteger           startsWith          slice
ă   imul        isNaN               endsWith            filter
Ą   fround      toInteger           trim                isArray
ą   log         parseFloat          trimLeft            lastIndexOf
Ć   max         parseInt            trimRight           indexOf
ć   min         length              toLocaleLowerCase   forEach
Ĉ   pow         name                toLocaleUpperCase   map
ĉ   random      arguments           normalize           every
Ċ   round       caller              match               some
ċ   sin                             search              reduce
Č   sqrt                            replace             reduceRight
č   tan                             split   
Ď   log10                           substr  
ď   log2                            concat  
Đ   log1p                           slice   
đ   expm1                           fromCharCode    
Ē   cosh                            fromCodePoint   
ē   sinh                            localeCompare   
Ĕ   tanh                            length  
ĕ   acosh                           name    
Ė   asinh                           arguments   
ė   atanh                           caller  
Ę   hypot           
ę   trunc           
Ě   sign            
ě   cbrt            
Ĝ   E           
ĝ   LOG2E           
Ğ   LOG10E          
ğ   LN2         
Ġ   LN10            
ġ   PI          
Ģ   SQRT2           
ģ   SQRT1_2         

ฉันใช้ google chrome และทุกอย่างให้ไม่ได้กำหนด
SuperJedi224

มันจะต้องมีความเฉพาะเจาะจงมาก firefox ขออภัยในความไม่สะดวก.
bebe

เหตุใดอักขระพิเศษเหล่านี้ทั้งหมดจึงมี ทำไมไม่ใช้แค่ ASCII ที่พิมพ์ได้? (พิมพ์ง่ายกว่าเชื่อถือได้มากขึ้นและมีเพียง 1 ไบต์สำหรับการเล่นกอล์ฟ)
Cyoce

สิ่งนี้ใช้งานไม่ได้Mathเพราะไม่มี.prototypeแอตทริบิวต์ อย่างไรก็ตามการลบออกMathฉันจัดการเพื่อเล่นกอล์ฟลงไปที่ข้อมูลขนาด 114 ไบต์ซึ่งกำหนดให้พวกเขาทั้งหมดเป็นตัวอักษรไบต์เดียว คุณสามารถค้นหาได้ที่นี่
ETHproductions

1
คุณยังสามารถตีกอล์ฟโซลูชันของฉันไปที่ 106 ไบต์โดยเสียค่าใช้จ่ายในการย้ายคุณสมบัติเหล่านี้ไปยังช่วงÀ- ÿซึ่งยังคงมี 1 ไบต์ในการเข้ารหัส ISO-8859-1 (ซึ่ง JS สนับสนุน) ใน Firefox 50 นี่เป็น.localeCompareวิธีการที่น่าเสียดาย×แต่ก็ไม่เป็นปัญหา แหล่งที่มา
ETHproductions

22

การแปลงwhileลูปเป็นforลูปมักจะเทียบเท่า:

while(i--);
for(;i--;);

แต่รูปแบบที่สองสามารถมีการเริ่มต้นตัวแปรรวม:

i=10;while(i--);
for(i=10;i--;);

ขอให้สังเกตว่ารูปแบบที่สองคือหนึ่งตัวละครที่สั้นกว่ารูปแบบแรก


6
หรือดียิ่งขึ้นเพียงใช้สำหรับลูป ไม่มีกรณีใดที่การใช้ลูป for เพื่อให้ได้รหัสขนาดใหญ่เท่าที่ฉันเคยพบมา
Isiah Meadows

22

ข้อยกเว้นที่ไม่เหมาะสม

ในกรณีที่ไม่อนุญาตให้ใช้ตัวอักษรสตริง / ตัวอักษรคุณสามารถใช้ลอง catch catch block:

try{something0}catch(e){str=e.message.split(0)[0]}

ตอนนี้strเท่ากับ"something"

ถ้าจำเป็นต้องใช้สายเพิ่มเติมคุณสามารถโยงมันด้วยตัวเลข (เช่นศูนย์)

try{something0foo0bar0}catch(e){arr=e.message.split(0)}

ตอนนี้arrเท่ากับ["something", "foo", "bar", " is not defined"]


18

หากคุณกำลังเริ่มต้นตัวแปรเป็น1ทุกรอบการวนซ้ำ (ตัวอย่างเช่นการรีเซ็ตตัวแปรในลูปภายนอกสำหรับลูปภายใน) เช่นต่อไปนี้ (จากคำตอบของฉันไปที่คำถามนี้ ):

for(j=n-2;p=1,j++<=n;r|=p)for(i=1;++i<j;)p=j%i?p:0;
          ^^^^

เนื่องจากผลลัพธ์ของเงื่อนไขเช่นj++<=nนี้คือ1เมื่อใดก็ตามที่เป็นจริงคุณสามารถกำหนดเงื่อนไขให้กับตัวแปรได้โดยตรง (เพราะเมื่อมันกลายเป็นเท็จลูปจะหยุดการทำงานและจะไม่สำคัญอีกต่อไป):

for(j=n-2;p=j++<=n;r|=p)for(i=1;++i<j;)p=j%i?p:0;
          ^^^^^^^^

โดยปกติคุณสามารถบันทึกอักขระได้ 2 ตัวโดยใช้วิธีนี้ เรื่องที่เกี่ยวกับ@ugorenความคิดในการแสดงความคิดเห็นที่จะตอบว่า


อีกตัวอย่างหนึ่งฉันยังใช้เคล็ดลับนี้กับคำตอบที่นี่พร้อมกับนิพจน์w=r=++c<S.lengthด้านนอกเพื่อวนซ้ำซึ่งช่วยประหยัดอักขระทั้งหมด 4 ตัว


18

หากคุณสามารถยอมรับ Spidermonkey (ตอนนี้) สคริปต์เฉพาะคุณสามารถใช้ECMAScript ฟังก์ชั่น การเริ่มต้นการเขียนโค้ดดังต่อไปนี้

a.map(function(x){return x*2}) // function? return?

คุณสามารถย่อให้สั้นลงได้เช่นนี้

a.map(x=>x*2)

17

หากคุณต้องการตรวจสอบ NaN อย่าใช้isNaN(x)แต่ใช้x!=xซึ่งสั้นกว่าและใช้งานได้

if(isNaN(x)){
if(x!=x){

โปรดทราบว่าสิ่งนี้ใช้ได้เฉพาะในกรณีtypeof(x) === "number"; ถ้าเป็นสตริงตัวอย่างเช่นisNaN("string")ผลตอบแทนtrueแต่ผลตอบแทน"string" != "string" falseขอบคุณ Cyoce ที่ชี้เรื่องนี้ออกมา!


2
นั่นคือการใช้ความสามารถพิเศษของการเล่นโวหารนี้ +1
ETHproductions

คำเตือน: สิ่งเหล่านี้ไม่เสมอไป: isNaN("string")ผลตอบแทนtrue, ในขณะที่"string"!="string"ผลตอบแทนfalse(ชัดเจน)
Cyoce

@Cyoce จุดดีขอบคุณ! ฉันแก้ไขคำตอบของฉัน
ProgramFOX

ในหลายกรณีคุณสามารถทำได้if(!x){หากคุณกำลังตรวจจับNaNอย่างชัดเจน
Hohmannfan

1
กำลังส่งxไปยังหมายเลขหมายถึง+x!=+xทำให้isNaN(x)สั้นลง แต่ยังสั้นกว่า 2 ตัวอักษร จากนั้น+"string"!=+"string"ส่งคืนค่าจริง
Tomas Langkaas

15

ผลรวมอาร์เรย์ / ผลิตภัณฑ์ / ผลหาร

ES5 : 17 ไบต์

eval(a.join('+'))

ES6 : 15 ไบต์

eval(a.join`+`)

แน่นอนคุณสามารถแลกเปลี่ยน+สิ่งที่คุณต้องการเช่น*สำหรับผลิตภัณฑ์หรือ/ผลหาร


14

ใช้การดำเนินการระดับบิตเพื่อปัดตัวเลขให้เป็นศูนย์

// do this
T=Math.random()*6+1|0

// or do this
T=~~(Math.random()*6+1)

(ที่มา: การให้ทิปลูกเต๋าแบบสุ่ม )

ตัวดำเนินการที่มาก่อนกำหนดว่าโปรแกรมใดจะสั้นลง


2
n=prompt()|0นอกจากนี้ยังสามารถนำมาใช้เพื่อเชื่อมต่อกันป้อนข้อมูลสตริงเป็นจำนวนเต็มคือ
mellamokb

1
bitwise นั้นเร็วสุดเมื่อเทียบกับ math.floor: jsperf.com/floor-vs-bitwise
vsync

@vsync: แปลก ฉันได้ math.floor เร็วกว่า bitwise ประมาณสองเท่าบน Chrome 11.0.696.77
mellamokb

แปลกมาก. สำหรับฉันพวกเขามีทั้งความเร็วเท่าเดิมและเร็วสุดใน Chrome แต่ใน FF ค่าบิตบิตนั้นเร็วกว่า Chrome มากและMath.floorช้ามาก .. ที่สุดไม่ควรใช้ฉันจะบอกว่า
vsync

เพื่อให้ความคิดเห็นทันสมัยอยู่เสมอใน Fx ปัจจุบันพวกเขาทั้งคู่รวดเร็วและเท่าเทียมกัน ไม่ว่ามันจะเป็นคอขวดในสถานที่แรกเมื่อเทียบกับรหัสโดยรอบ ...
FireFly

14

เคล็ดลับการวนรอบฉัน

คุณสามารถบันทึก1ตัวละครเมื่อวนลูปโดยการเปลี่ยนiในครั้งล่าสุดที่ใช้:

//not so god
for(i=0;i<3;i++){
  alert(i);
}

//best
for(i=0;i<3;){
  alert(i++);
}

หมายเหตุ: ใช้งานได้--เช่นกัน (แต่แก้ไขลูปตามลำดับเพื่อหลีกเลี่ยงการวนซ้ำไม่ จำกัด )


เคล็ดลับการวนรอบ II

มีบางสถานการณ์ที่คุณสามารถบันทึกหนึ่งตัวละครโดยการเล่นกับโอเปอเรเตอร์และค่าที่เพิ่มขึ้น:

for(i=0;i++<9;)
for(i=0;++i<10;)

หมายเหตุ:0 to -1คุณจำเป็นต้องให้ความสนใจเมื่อยกตัวอย่างเช่น และ9 to 10, 99 to 100เล่นไปเรื่อย ๆ จนกว่าคุณจะพบวิธีที่จะช่วยตัวละคร


13

ใช้^แทน!=หรือ==เมื่อเปรียบเทียบกับจำนวนเต็ม

//x!=3?a:b
  x^3?a:b

//x==3?a:b
  x^3?b:a

แทนที่การเรียกไปยังฟังก์ชันคณิตศาสตร์ในตัวด้วยนิพจน์ที่สั้นกว่า

//Math.ceil(n)
  n%1?-~n:n

//Math.floor(n)
  ~~n
  0|n

//Math.abs(n)
  n<0?-n:n

//Math.round(n)
  n+.5|0

//Math.min(x,y)
  x<y?x:y

//Math.max(x,y)
  y<x?x:y

2
หรือคุณสามารถใช้-แทน!=จำนวนเต็มได้ ตัวอย่างเช่นn!=1?a:bจะเท่ากับn-1?a:b
vrugtehagel

10

สิ่งที่ควรสังเกตคือคุณสามารถใช้สตริงแทนศูนย์ในบางกรณีเพื่อบันทึกสองสามไบต์ที่นี่และมีลูป:

s='';for(i=0;i++<9;)s+=i
for(i=s='';i++<9;)s+=i
// s="123456789", i=10

1
ฉันลอง "" ++ ในคอนโซลก่อนหน้านี้สงสัยว่ามันใช้งานได้หรือไม่แน่นอนว่ามันต้องอยู่ในตัวแปรก่อน ขอบคุณ!
Vartan

10

ง่ายมากแม้ไม่มีใครพูดถึงมัน

หากคุณใช้Math.min()หรือMath.max()คุณสามารถบันทึกได้ 6 ตัวอักษรโดยทำดังนี้

Math.min(a,b)  // 13 chars
a<b?a:b        //  7 chars

Math.max(a,b)
a>b?a:b

10

การล้อม

ฉันรู้ว่ามีทางเลือกอื่น ๆ สำหรับMath.floor()การโพสต์ แต่สิ่งที่เกี่ยวกับคนอื่น ๆ ?

พื้น:

Math.floor(x) //before
0|x           //after

ปัดเศษ:

Math.round(x) //before
0|x+.5        //after

เพดาน:

Math.ceil(x) //before
x%1?-~x:x    //after - credits to @Tomas Langkaas

1
โปรดทราบว่า0|x+1เพียงแค่เพิ่ม 1 ถ้าจำนวนที่คุณต้องการหาฝ้าเพดานของเป็นจำนวนเต็มแล้ว ทางเลือกที่ปลอดภัย (ส่วนใหญ่) คือ0|x+1-1e9แต่จะสั้นกว่าเพียงสามไบต์
ETHproductions

@ETHproductions คุณไม่ได้หมายถึง0|x+1-1e-9อะไร
Mama Fun Roll

โอ๊ะโอ ขอบคุณสำหรับการชี้ให้เห็นว่า (ด้วยเหตุผลบางอย่างฉันไม่สามารถทำ @ (ชื่อผู้ใช้ของคุณ) ... )
ETHproductions

อาจเป็นเพราะตัวอักษรชื่อผู้ใช้ของฉันคว่ำอยู่ :)
Mama Fun Roll

1
สำหรับเพดานx%1?-~x:x(9 ตัวอักษร) เป็นทางเลือกที่ดีกว่า อย่างไรก็ตามเช่นเดียวกับทางเลือกพื้น0|xและ~~xมันใช้งานได้สำหรับตัวเลขบวก
Tomas Langkaas

9

ในกรณีที่คุณกำลังใช้ตัวดำเนินการแบบไตรภาคเพื่อเลือกระหว่างตัวเลขสองตัวและเงื่อนไขนั้นเป็นบูลีนหรือตัวเลข 1 or 0คุณสามารถทำการดำเนินการทางคณิตศาสตร์แทน:

(x ? num1 : num2) conclusions:

    1)if num1 equals num2, there ARE savings
    2)if num1 is (+1) or (-1) than num2, there ARE savings
    3)if either num1 or num2 equals to 0, there ARE savings
    4)it is MORE LIKELY to find greater savings on num1>num2 instead of num1<num2
    5)in method (*A) and (*B), savings are NOT GUARANTEED

    a)num1>num2
        i)(num1==(num2+1))
            ex1: (x?5:4) to (x+4)
            ex2: (x?8:7) to (x+7)
        ii)num2==0
            ex1: (x?3:0) to (x*3)
            ex2: (x?7:0) to (x*7)
        iii)
            (*A) or (*B) //one might be shorter

    b)num1<num2
        i)((num1+1)==num2)
            ex1: (x?4:5) to (5-x)
            ex2: (x?7:8) to (8-x)
        ii)num1==0
            ex1: (x?0:3) to (!x*3)
            ex2: (x?0:7) to (!x*7)
        iii)
            (*A) or (*B) //one might be shorter

    c)num1==num2
        i)
            ex1: (x?5:5) to (5)
            ex2: (x?-3:-3) to (-3)

    (*A) use ((x*(num1-num2))+num2)
        ex1: (x?8:4)   to ((x*4)+4)
        ex2: (x?4:8)   to ((x*-4)+8)

        ex3: (x?6:-4)  to ((x*10)-4)
        ex4: (x?-4:6)  to ((x*-10)+6)

        ex5: (x?4:-6)  to ((x*10)-6)
        ex6: (x?-6:4)  to ((x*-10)+4)

        ex7: (x?-5:-9) to ((x*4)-9)
        ex8: (x?-9:-5) to ((x*-4)-5)

    (*B) use ((!x*(num2-num1))+num1)
        ex1: (x?8:4)   to ((!x*-4)+8)
        ex2: (x?4:8)   to ((!x*4)+4)

        ex3: (x?6:-4)  to ((!x*-10)+6)
        ex4: (x?-4:6)  to ((!x*10)-4))

        ex5: (x?4:-6)  to ((!x*-10)+4)
        ex6: (x?-6:4)  to ((!x*10)-6)

        ex7: (x?-5:-9) to ((!x*-4)-5)
        ex8: (x?-9:-5) to ((!x*4)-9)

หมายเหตุ:นอกจากนี้คุณจะต้องลบที่ไม่จำเป็น0-, +0, +-ฯลฯ

Note2:มีกรณีที่แยกที่(x) !== (x?1:0)เป็นxจะต้องมีtypeof === "number"เพื่อให้การทำงาน อย่างไรก็ตามในกรณีที่(-x)มันใช้งานได้ดี

Note3:ในกรณีที่คุณไม่พบเงินออมให้ใช้วิธีเดิม(x?y:z)

ก่อนหน้านี้ฉันคิดว่าวิธี B ไม่สามารถเอาชนะ A ได้ แต่มีข้อยกเว้นอยู่:

(x?97:100) //original

(-3*x+100)
(3*!x+97)

ฉันสร้างโครงการ GitHubที่ทำให้เราเข้าใจง่ายขึ้น ( สาธิต jsFiddle )


@ ajax333221 void 0(มันไม่ได้เป็นฟังก์ชั่น แต่คำหลัก) undefinedไม่ใช่ค่ามันก็ผลตอบแทน
Camilo Martin

@CamiloMartin คุณพูดถูกฉันก็เห็นประเด็นในคำตอบนี้แล้ว แต่aต้องเป็น 1 หรือ 0 เพื่อให้สามารถใช้งานได้
ajax333221

@ ajax333221 ใช่จริง ๆ แล้วเรื่องตลกเกี่ยวกับการตีกอล์ฟกับฉันคือกลวิธีที่ดีที่สุดส่วนใหญ่ทำงานได้เฉพาะกับสิ่งที่คุณกำลังทำอยู่และรู้สึกฉลาดเพื่อหาเคสมุมเหล่านี้ด้วยโซลูชันมุม: D By the วิธีคุณไม่ต้องลบความคิดเห็น ...
Camilo Martin

9

tl; dr:ใช้คุณสมบัติ ES6!

ฟังก์ชั่นลูกศร

Doc: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/arrow_functions
ตัวอย่าง:

s = x => x*x
// s = function (x) {
//   return x * x;
// }

ฟังก์ชั่นลูกศรถูกกล่าวถึงแล้วในวันที่ 13 ต.ค. 13 เวลา 15:42 น . แต่นั่นก็เท่for.. ofแม้จะสั้นกว่า..for each in
ผลิต

2
ไวยากรณ์ของความเข้าใจอาร์เรย์ดูเหมือนจะผิด อ้างอิงถึงเอกสารที่b = [s(x) for (x of a)]ควรจะเป็นอย่างในหลาม:
จัดการ

@ manatwork ตัวอย่างข้างต้นทำงานได้ดีใน REPL ของ Traceur
Florent

ไม่มีความคิดเกี่ยวกับ Traceur แต่คุณพูดถึง ECMAScript และชี้ไปที่เอกสารประกอบของ Mozilla และความเข้าใจในแถวลำดับในไม่มีพวกเขาดูเหมือนคุณเขียนมัน
ผลิต

1
ความเข้าใจของอาร์เรย์ถูกดึงผ่านกลางคันจริง ๆ
Isiah Meadows

9

ใช้ตัวอักษรที่ไม่เหมาะสม

ตัวอย่างล่าสุด: ตรวจสอบว่า"c"เป็นตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็กไม่สำคัญว่าจะไม่ใช่ตัวอักษร

"c"<{} // returns false, lower case
"C"<{} // returns true, upper case

3
มันทำงานอย่างไร
วัวต้มตุ๋น

2
@Cowsquack ให้String({}) "[object Object]"
Dennis

8

วิธีเปรียบเทียบตัวเลขด้วยความช่วยเหลือของการเปลี่ยนตัวเลขเป็นบูลีน:

หากคุณกำลังจะตรวจสอบว่ามีบางสิ่งบางอย่างเท่ากับจำนวนบวกคุณสามารถลบจำนวนนั้นและย้อนกลับสิ่งที่อยู่ภายในifและelseบล็อก:

//simplified examples:
x==3?"y":"n"; <- 13 Chars
x-3?"n":"y"; <- 12 Chars

//expanded examples:
if(x==3){
    yes();
}else{
    no();
}

if(x-3){
    no();
}else{
    yes();
}

และในกรณีที่คุณต้องการเปรียบเทียบกับจำนวนลบ (* แตกต่างจาก-1) คุณเพียงแค่เพิ่มหมายเลขนี้แทนการลบ

* ดีคุณสามารถใช้แน่นอนx.indexOf(y) + 1แต่ในกรณีพิเศษที่-1คุณมีโอกาสใช้~x.indexOf(y)แทน


8

ใช้ฟีเจอร์ "การปิดนิพจน์" ที่ไม่เป็นมาตรฐานของ Mozilla เพื่อบันทึกอักขระจำนวนมากในสคริปต์ที่จำเป็นต้องใช้ในเครื่องมือ SpiderMonkey / Firefox หรือ Rhino เท่านั้น ตัวอย่างเช่น,

function foo(){return bar}

กลายเป็น

function foo()bar

ดูที่กองซ้อนล้นหน้าสำหรับเทคนิคดังกล่าวเพิ่มเติม


2
นั่นไม่ใช่จาวาสคริปต์ นั่นคือสถานีอวกาศ !!!
Thomas Eding

1
ECMAScript 6 เพื่อช่วยเหลือ! ->bar
Ry-

5
ECMAScript 6: let foo = () => bar;สั้นกว่าโค้ดกอล์ฟที่กล่าวมาข้างต้น
Isiah Meadows

1
ECMAScript 6: foo=_=>barยิ่งสั้น
ETHproductions

ลิงก์นั้นใช้งานไม่ได้
Cyoce


8

แทนการเขียนคุณสามารถใช้true!0


4
ในทำนองเดียวกันสำหรับ!1 false
James M. Lay

10
ยังดีกว่าใช้1สำหรับtrueและ0สำหรับfalseเว้นแต่คุณจะต้องการค่าตัวอักษรจริงๆ
ETHproductions

8

แปลงร่างเป็นบูลีน :

if(b){b=true}else{b=false}
b=b?true:false;
b=b?!0:!1;
b=!!b;

หมายเหตุ:การเปลี่ยนแปลงนี้0, "", false, null, undefinedและNaNเพื่อfalse(ทุกอย่างอื่นtrue)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.