> 웹 프론트엔드 > JS 튜토리얼 > JavaScript가 쉽게 속일 수 있는 문제

JavaScript가 쉽게 속일 수 있는 문제

hzc
풀어 주다: 2020-06-28 09:50:23
앞으로
2257명이 탐색했습니다.

머리말

요약: 이것은 제가 더 흥미롭거나 어렵다고 생각하는 일부 JavaScript 주제에 대한 이해와 경험이며 장기적으로 업데이트될 것입니다.

여자로 살지 마세요. 그러면 당신의 행복과 고통은 백년 동안 남에게 맡겨질 것입니다.

Text

1. setTimeout 및 setInterval에 대한 심층적 이해

setTimeout 및 setInterval에 대한 심층적 이해에 대한 이 블로그 게시물에서 저자는 JavaScript가 단일 스레딩의 산물임을 알고 있습니다. 두 함수는 코드를 삽입하는 방식을 사용하는데, 이는 실제로 AJAX와 동일한 원리입니다. 다음 예를 살펴보겠습니다.

console.log("1");
setTimeout(function(){        
    console.log("3")
},0);    console.log("2");
로그인 후 복사

결과: 콘솔은 1, 2, 3을 순서대로 출력합니다.

function fn() {
    setTimeout(function(){alert('can you see me?');},1000);
    while(true) {}
}
로그인 후 복사

이 코드의 실행 결과는 무엇이라고 생각하시나요? 대답은 경고가 결코 나타나지 않는다는 것입니다.
왜 이럴까요? while 코드가 실행되지 않았기 때문에 나중에 삽입된 코드는 절대 실행되지 않습니다.
결론적으로 JS는 결국 싱글스레드 제품입니다. 아무리 "비동기적"이라고 해도 단일 스레드 장벽을 돌파하는 것은 불가능합니다. 따라서 많은 "비동기 호출"(Ajax 포함)은 실제로는 "의사 비동기"입니다. 이러한 개념을 이해한다면 setTimeout과 setInterval을 이해하는 것은 어렵지 않을 것입니다.

2. 클로저의 예비 탐색

블로그 "JavaScript 클로저의 초기 탐색"에서 예비 토론을 진행했습니다. 제가 개인적으로 꽤 흥미롭다고 생각하는 몇 가지 질문이 있습니다:

  var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      return function(){
        return this.name;
      };
    }
  };
  alert(object.getNameFunc()());//The Window
로그인 후 복사
   var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };
    }
  };  
  alert(object.getNameFunc()());//My Object
로그인 후 복사
function fun(n,o) {
  console.log(o)
  return {
    fun:function(m){
      return fun(m,n);
    }
  };
}
var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);//undefined,?,?,?
var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?
var c = fun(0).fun(1);  c.fun(2);  c.fun(3);//undefined,?,?,?
로그인 후 복사

//질문: 세 줄 a 그리고 b, c의 출력은 무엇입니까?

이것은 매우 일반적인 JS 폐쇄 문제입니다. 그 안에는 세 가지 수준의 재미있는 기능이 내재되어 있습니다. 각 수준의 재미있는 기능이 어떤 재미있는 기능인지 파악하는 것이 특히 중요합니다.

//답변:
//a: 정의되지 않음,0,0,0
//b: 정의되지 않음,0,1,2
//c: 정의되지 않음,0,1,1

3. /map,Number/parseInt

["1", "2", "3"].map(parseInt)//求输出结果复制代码
로그인 후 복사

먼저 map은 콜백 함수 콜백과 콜백 함수의 this 값이라는 두 가지 매개변수를 허용합니다.
콜백 함수는 currentValue, index, array라는 세 가지 매개변수를 허용하며, 질문에서는 map만 전달합니다. 콜백 함수 --parseInt에서 두 번째로,parseInt는 radix(radix)라는 두 개의 매개변수만 허용합니다. radix의 유효한 범위는 ​​2-36입니다. 또는 기본값은 10입니다. 따라서 이 질문은 후자 2개에 관한 것입니다.

parseInt('1', 0);parseInt('2', 1);parseInt('3', 2);复制代码
로그인 후 복사
매개변수는 불법입니다. [1, NaN, NaN];

4.0.1+0.2!=0.3 및 999999999999999 == 10000000000000000

언어 사양에 따르면 IEEE 754 표준에 의해 정의된 64" "배정밀도 64비트 형식 IEEE 754 값"("배정밀도 64비트 형식 IEEE 754 값")은 숫자를 나타냅니다. 이것으로부터 우리는 흥미로운 결론을 도출할 수 있습니다. 다른 프로그래밍 언어(예: C 및 Java)와 달리 JavaScript는 정수 값과 부동 소수점 값을 구분하지 않습니다. 따라서 수치 연산을 수행할 때는 특별한 주의를 기울이십시오. 정밀도 손실 다음 예를 살펴보세요.

0.1 + 0.2 = 0.30000000000000004复制代码
로그인 후 복사
특정 구현에서는 정수 값이 일반적으로 32비트 정수 변수로 처리되며, 개별 구현(일부 브라우저 등)에서는 정수 값도 다음과 같은 형식입니다. 32비트 정수 변수 32비트 정수에서 지원하지 않는 일부 작업을 수행하는 데 사용될 때까지 저장되며, 이는 비트 조작을 용이하게 하기 위한 것입니다. 큰 정수의 정밀도는 2의 53승 내에서 손실되지 않습니다. 즉, 유한 숫자가 a의 이진 표현으로 표시되는 경우 브라우저가 Math.pow(2,53) 내의 모든 숫자를 정확하게 계산할 수 있음을 의미합니다. 10진수는 52비트를 초과하면 자바스크립트에서도 정확하게 저장할 수 있습니다.

해결책: Math.round( (.1+.2)*100)/100;

5. [1<2<3,3<2<1]

이 질문은 사람들이 2>라고 잘못 생각하게 만들 것입니다. ;1&&2<3, 사실, 아니요, 이 질문은

1<2=>true;true<3=>1<3=>true;3<2=>true;false<1=>0<1=>true;复制代码<p>답변: [true, true]<strong>와 동일합니다. 이 질문의 초점은 연산자에 대한 이해에 있습니다. 첫 번째는 다양한 유형의 JavaScript 비교 규칙입니다. 값에 대한 자세한 내용은 js 비교표를 참조하세요. 두 번째는 비교 연산자와 할당 연산자, 즉 왼쪽에서 오른쪽으로 하나씩에 대한 이해입니다~</strong></p>6. )<h3 id="6-1-" data-id="heading-7"><pre class="brush:php;toolbar:false">3.toString;3..toString;3...toString;复制代码
로그인 후 복사
이 질문은 매우 상상력이 풍부한 것 같습니다~ 먼저 답을 말씀드리겠습니다: error,'3',error;

하지만

var a=3;
a.toString;复制代码
로그인 후 복사
이지만 합법적이라면 답은 '3'입니다.

왜요?
JS에서는 1.1, 1.,.1이 모두 유효한 숫자이기 때문이죠! 그러면 3.toString을 구문 분석할 때 이것이 숫자입니까, 아니면 메소드 호출입니까? 브라우저가 혼란스럽고 오류만 던질 수 있어서 이 질문은 브라우저에서 장난을 치는 것 뿐이라는 느낌이 듭니다...

7. 문장 개선

var name = 'World!';
(function () {
    if (typeof name === 'undefined') {
        var name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();
로그인 후 복사

답은 무엇인가요... 작성자가 첫 번째입니다. 했을 때, 나는 어리석게도 Hello, world라고 생각했습니다... 그러나 정답은 다음과 같습니다: Goodbye Jack

왜, 문장이 개선되었습니까? 위의 코드는 다음 코드와 동일합니다. :

var name = 'World!';
(function () {
    var name;
    if (typeof name === 'undefined') {
        name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();
로그인 후 복사

8. 坑爹史(1)

var a = [0];
if ([0]) {
  console.log(a == true);
} else {
  console.log("wut");
}
로그인 후 복사

读者们你们觉得此题答案是什么呢?true?因为[0]被看做Boolean是被认为是true,理所当然的推出来[0]==true,控制台输出true...看似没错,然而并不是这样滴~[0]这个玩意儿在单独使用的时候是被认为是true的,但用作比较的时候它是false...所以正确答案是false;不信的话,F12控制台输出[0]==false;看是不是true......

###9. 坑爹史(2)

1 + - + + + - + 1
로그인 후 복사

这题应该是等同于:(倒着看)

1 + (a)  => 2
a = - (b) => 1
b = + (c) => -1
c = + (d) => -1
d = + (e) => -1
e = + (f) => -1
f = - (g) => -1
g = + 1   => 1
로그인 후 복사

答案是2

10. 坑爹史(3)

function sidEffecting(ary) {
  ary[0] = ary[2];
}
function bar(a,b,c) {
  c = 10
  sidEffecting(arguments);  return a + b + c;
}
bar(1,1,1)
로그인 후 복사

此题涉及ES6语法,实在坑的不行...arguments
首先 The arguments object is an Array-like object corresponding to the arguments passed to a function.也就是说 arguments 是一个 object, c 就是 arguments2, 所以对于 c 的修改就是对 arguments2 的修改.
所以答案是 21.
然而!!!!!!
当函数参数涉及到 any rest parameters, any default parameters or any destructured parameters 的时候, 这个 arguments 就不在是一个 mapped arguments object 了.....请看:

function sidEffecting(ary) {
  ary[0] = ary[2];
}
function bar(a,b,c=3) {
  c = 10
  sidEffecting(arguments);  return a + b + c;
}
bar(1,1,1)
로그인 후 복사

答案是12...
请读者细细体会!!

11. 坑爹史(4)

[,,,].join(", ")
로그인 후 복사
[,,,] => [undefined × 3]
로그인 후 복사

因为javascript 在定义数组的时候允许最后一个元素后跟一个,, 所以这是个长度为三的稀疏数组(这是长度为三, 并没有 0, 1, 2三个属性哦)
答案: ", , "

12. 浏览器懵逼史(2)

var a = {class: "Animal", name: 'Fido'};
a.class
로그인 후 복사

这个题比较流氓.. 因为是浏览器相关, class是个保留字(现在是个关键字了);Fuck!
所以答案不重要, 重要的是自己在取属性名称的时候尽量避免保留字. 如果使用的话请加引号 a['class']

13.一道容易被人轻视的面试题

function Foo() {
    getName = function () { alert (1); };
    return this;
}
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
var getName = function () { alert (4);};
function getName() { alert (5);}

//请写出以下输出结果:
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
로그인 후 복사

14.闭包小题

for(var i = 0; i < 5; i++) {
    console.log(i);
}

for(var i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000 * i);
}

for(var i = 0; i < 5; i++) {
    (function(i) {
        setTimeout(function() {
            console.log(i);
        }, i * 1000);
    })(i);
}

for(var i = 0; i < 5; i++) {
    (function() {
        setTimeout(function() {
            console.log(i);
        }, i * 1000);
    })(i);
}

for(var i = 0; i < 5; i++) {
    setTimeout((function(i) {
        console.log(i);
    })(i), i * 1000);
}

setTimeout(function() {
  console.log(1)
}, 0);
new Promise(function executor(resolve) {
  console.log(2);
  for( var i=0 ; i<10000 ; i++ ) {
    i == 9999 && resolve();
  }
  console.log(3);
}).then(function() {
  console.log(4);
});
console.log(5);
로그인 후 복사

15. 函数的隐式转换

function fn() {
    return 20;
}
console.log(fn + 10); // 输出结果是多少

function fn() {
    return 20;
}

fn.toString = function() {
    return 10;
}

console.log(fn + 10);  // 输出结果是多少?

function fn() {
    return 20;
}

fn.toString = function() {
    return 10;
}

fn.valueOf = function() {
    return 5;
}

console.log(fn + 10); // 输出结果是多少?
로그인 후 복사

16. 函数防抖和函数节流(ES6)

//函数节流
const throttle = (fun, delay) => {
    let last = null;
    return () => {
        const now = + new Date();
        if (now - last > delay) {
            fun();
            last = now;
        }
    }
}
//实例
const throttleExample  = throttle(() => console.log(1), 1000);
//调用
throttleExample();
throttleExample();
throttleExample();
//函数防抖
const debouce = (fun, delay) => {
    let timer = null;
    return () => {
        clearTimeout(timer);
        timer = setTimeout(() => {
            fun();
        }, delay);
    }
}
//实例
const debouceExample = debouce(() => console.log(1), 1000);
//调用
debouceExample();
debouceExample();
debouceExample();
로그인 후 복사

推荐教程:《JS教程

위 내용은 JavaScript가 쉽게 속일 수 있는 문제의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:juejin.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿