掌握 Javascript 的资源 掌握 Javascript

2025-05-24

掌握 JavaScript 的资源

掌握 Javascript

掌握 Javascript

Fork、Star GITHub 链接

Javascript 基础知识阅读:

http://dmitrysoshnikov.com/category/ecmascript/

http://exploringjs.com/impatient-js/ch_syntax.html#statement-vs.expression
https://github.com/getify/You-Dont-Know-JS/blob/master/up%20%26%20going/ch1.md
https://stackoverflow.com/questions/12703214/javascript-difference-between-a-statement-and-an-expression

  • 值和类型

http://speakingjs.com/es5/ch08.html
https://github.com/getify/You-Dont-Know-JS/blob/master/up%20%26%20going/ch1.md#values--types
https://github.com/getify/You-Dont-Know-JS/blob/master/up%20%26%20going/ch2.md

原始值与对象
http://speakingjs.com/es5/ch01.html#basic_prim_vs_obj

手动转换为布尔值
任何值可以通过三种方式转换为布尔值:

1)Boolean(value)

(Invoked as a function, not as a constructor)

2)value ? true : false

3)!!value
https://stackoverflow.com/questions/10467475/double-negation-in-javascript-what-is-the-purpose
var x = "somevalue"
var isNotEmpty = !!x.length;
Let's break it to pieces:

x.length   // 9
!x.length  // false
!!x.length // true
So it's used convert a "truethy" \"falsy" value to a boolean.

Enter fullscreen mode Exit fullscreen mode

单个“not”转换为否定布尔值;使用两次可进行非否定转换。

var a = "0";
var b = [];
var c = {};

var d = "";
var e = 0;
var f = null;
var g;

!!a;    // true
!!b;    // true
!!c;    // true

!!d;    // false
!!e;    // false
!!f;    // false
!!g;    // false
Enter fullscreen mode Exit fullscreen mode

https://stackoverflow.com/questions/9959727/proto-vs-prototype-in ​​-javascript )

https://stackoverflow.com/questions/27509/detecting-an-undefined-object-property


嗯,它们在语义上是不同的,作为函数调用的 Number 构造函数执行类型转换,而 parseInt 执行解析。

但在实际生活中,我们经常使用单位值,例如 CSS 中的“100px”或“12pt”。此外,在许多国家/地区,货币符号位于金额后面,因此我们想从“19€”中提取一个数值。

这就是 parseInt 和 parseFloat 的用途。

它们会从字符串中“读取”一个数字,直到读不出来为止。如果发生错误,则返回收集到的数字。parseInt
函数返回一个整数,而 parseFloat 函数返回一个浮点数:

 alert( parseInt('100px') ); // 100
alert( parseFloat('12.5em') ); // 12.5

alert( Number("   123   ") ); // 123
alert( Number("123z") );      // NaN (error reading a number at "z")
alert( Number(true) );        // 1
alert( Number(false) );       // 0
Enter fullscreen mode Exit fullscreen mode

http://speakingjs.com/es5/ch11.html#isNaN最佳

https://stackoverflow.com/questions/2652319/how-do-you-check-that-a-number-is-nan-in-javascripthttps://stackoverflow.com/questions/825402/why-does-isnan-equal-falsehttps://stackoverflow.com/questions/8965364/comparing-nan-values-for-equality-in-javascripthttps://stackoverflow.com/questions/6736476/how-to-turn-nan-from-parseint-into-0-for-an-empty-stringhttps://stackoverflow.com/questions/34261938/what-is-the-difference-between-nan-nan-and-nan-nanhttps://stackoverflow.com/questions/20534887/break-on-nan-in-javascript



https://stackoverflow.com/questions/26962341/number-isnan-doesnt-exist-in-ie
https://stackoverflow.com/questions/15176076/understanding-underscores-implementation-of-isnan

我建议:typeof value === 'number' && !isNaN(value)。因为 typeof NaN === 'number'。

NaN 是唯一不等于其自身的值:


> NaN === NaN
false

Enter fullscreen mode Exit fullscreen mode

因此我们可以使用如果要检查一个值是否为 NaN,则必须使用全局函数 isNaN():

> isNaN(NaN)
true
> isNaN(33)
false


Enter fullscreen mode Exit fullscreen mode

但是 :
isNaN 函数无法正确处理非数字,因为它会先将非数字转换为数字。这种转换可能会产生 NaN,然后​​函数会错误地返回 true:


> isNaN('xyz')
true


Enter fullscreen mode Exit fullscreen mode

因此,最好将 isNaN 与类型检查结合起来:

function myIsNaN(value) {
    return typeof value === 'number' && isNaN(value);
}


Enter fullscreen mode Exit fullscreen mode

或者,你可以检查该值是否不等于其自身(因为 NaN 是唯一具有此特征的值)。但这不太容易理解:

function myIsNaN(value) {
    return value !== value;
}

Enter fullscreen mode Exit fullscreen mode

isNaN() 和 Number.isNaN() 都用于测试一个值是否为 NaN 值(或者,在 isNaN() 的情况下,可以将其转换为表示 NaN 值的数字类型值)。换句话说,“NaN”并非简单地表示“这个值不是数字”,而是具体表示“根据 IEEE-754,这个值是一个非数字类型的数值”。

上述所有测试都返回 false 的原因是因为所有给定的值都可以转换为非 NaN 的数值:

Number('')    // 0
Number('   ') // 0
Number(true)  // 1
Number(false) // 0
Number([0])   // 0
Enter fullscreen mode Exit fullscreen mode

isNaN() 之所以“失效”,表面上是因为在测试值时不应该进行类型转换。而 Number.isNaN() 正是为此而设计的。具体来说,只有当值是数字类型时,Number.isNaN() 才会尝试将其与 NaN 进行比较。任何其他类型都会返回 false,即使它们字面上“不是数字”,因为 NaN 值的类型就是数字。请参阅 isNaN() 和 Number.isNaN() 各自的 MDN 文档。

如果您只是想确定某个值是否属于数字类型,即使该值是 NaN,也可以使用 typeof:

typeof 'RAWRRR' === 'number' // false

某些内容尚未初始化:undefined。
某些内容当前不可用:null。

如果要使用其类型测试空值,则需要一个复合条件:

var a = null;

(!a && typeof a === "object"); // true

When youre trying to identify null, use triple equals so that you can correctly identify the type.
ex : console.log(undefined == null); // true
console.log(undefined === null); // false
Enter fullscreen mode Exit fullscreen mode

null 是唯一一个“falsy”(又名 false-like;参见第 4 章)的原始值,但它也从 typeof 检查中返回“object”。

陷阱:typeof null
很遗憾,typeof null 是“object”。这被认为是一个 bug(null 不是内部类型 Object 的成员),但无法修复,因为修复会破坏现有代码。因此,你必须对 null 保持警惕。例如,以下函数检查 value 是否为对象:

函数 isObject(value) {
return (value !== null
&& (typeof value === 'object'
|| typeof value === 'function'));

  • 原型中使用 null使用 null 原型,防止原型污染

function C() { }
C.prototype = null;
But instantiating this constructor still results in instances of Object:
var o = new C();
Object.getPrototypeOf(o) === null; // false
Object.getPrototypeOf(o) === Object.prototype; // true

Enter fullscreen mode Exit fullscreen mode

使用加号 + 或 Number() 进行的数字转换非常严格。如果值不是精确的数字,转换会失败:
alert( +"100px" ); // NaN

在某些情况下,parseInt/parseFloat 会返回 NaN。这种情况发生在无法读取任何数字时:

alert( parseInt('a123') ); // NaN,第一个符号停止进程

与 (&&)
如果第一个操作数为假,则返回它。否则,返回第二个操作数:

> NaN && 'abc'
NaN
> 123 && 'abc'
'abc'
Or (||)
If the first operand is truthy, return it. Otherwise, return the second operand:

> 'abc' || 123
'abc'
> '' || 123
123

var a = 42;
var b = "abc";
var c = null;

a || b;     // 42
a && b;     // "abc"

c || b;     // "abc"
c && b;     // null

a || b;
// roughly equivalent to:
a ? a : b;

a && b;
// roughly equivalent to:
a ? b : a;

Enter fullscreen mode Exit fullscreen mode

https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch2.md#testing-for-integers
42.3 % 1 是十进制,但 42 % 1 是 0

Number.isInteger( 42 );     // true
Number.isInteger( 42.000 ); // true
Number.isInteger( 42.3 );   // false

this behaviour can be use in :  
To polyfill Number.isInteger(..) for pre-ES6:

if (!Number.isInteger) {
    Number.isInteger = function(num) {
        return typeof num == "number" && num % 1 == 0;
    };
}

Enter fullscreen mode Exit fullscreen mode

摘自书籍:《Effective JavaScript:68 种驾驭 JavaScript 力量的具体方法》

本章让我了解了更多有关闭包和范围的隐藏知识。

https://www.safaribooksonline.com/library/view/effective-javascript-68/9780132902281/ch02.html#ch02lev1sec4

https://stackoverflow.com/questions/111102/how-do-javascript-closures-work
https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example
https://stackoverflow.com/questions/592396/what-is-the-purpose-of-a-self-executing-function-in-javascript
https://stackoverflow.com/questions/2728278/what-is-a-practical-use-for-a-closure-in-javascript
https://stackoverflow.com/questions/1451009/javascript-infamous-loop-issue

在与...在

for-in 语句本身并不是一个“坏习惯”,但它可能会被误用,
例如,迭代数组或类似数组的对象。

for-in 语句的目的是枚举对象属性。
该语句会沿着原型链向上执行,同时枚举继承的属性,而这有时并非我们所期望的。

for..in 不能保证保留元素顺序

https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch5.md

https://www.w3schools.com/jsref/jsref_forin.asp
https://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-a-bad-idea

http://adripofjavascript.com/blog/drips/the-problem-with-for-in-and-javascript-arrays.html

强迫

  • 相等性比较和相同性

强迫

http://speakingjs.com/es5/ch09.html
http://speakingjs.com/es5/ch10.html
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness )
http://ecma-international.org/ecma-262/5.1/#sec-11.9.3 )
http://getify.github.io/coercions-grid/ )

http://speakingjs.com/es5/ch09.html
用例:处理字符串中的数字
如果您不确定值 x 是数字还是字符串数字,则可以使用如下检查:


if (x == 123) ...

Enter fullscreen mode Exit fullscreen mode

上述代码检查 x 是否为 123 或 '123'。同样,这非常简洁,而且最好还是明确一点:

if (Number(x) === 123)

Enter fullscreen mode Exit fullscreen mode

用例:将包装器实例与原语进行比较
Lenient equals 允许您将原语与包装的原语进行比较:


> 'abc' == new String('abc')
true
Enter fullscreen mode Exit fullscreen mode

反对这种方法的理由有三个。首先,宽松的相等性在包装的原语之间不起作用:

> new String('abc') == new String('abc')
false
Second, you should avoid wrappers anyway. 
Third, if you do use them, it is better to be explicit:

if (wrapped.valueOf() === 'abc') 

Enter fullscreen mode Exit fullscreen mode

https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch4.md#comparing-strings-to-numbers

var a = "42";

// bad (will fail!):
if (a == true) {
    // ..
}

// also bad (will fail!):
if (a === true) {
    // ..
}

// good enough (works implicitly):
if (a) {
    // ..
}

// better (works explicitly):
if (!!a) {
    // ..
}

// also great (works explicitly):
if (Boolean( a )) {
    // ..
}

Enter fullscreen mode Exit fullscreen mode

Object.is
https://javascript.info/number

这个表达式是如何求值的?x < y *算法
http://speakingjs.com/es5/ch08.html#toprimitive)https://javascript.info/object-toprimitive

你评估一下比较:

x < y
Enter fullscreen mode Exit fullscreen mode

通过采取以下步骤:

确保两个操作数都是原始类型。对象 obj 通过内部操作 ToPrimitive(obj, Number) 转换为原始类型(参见算法:ToPrimitive()——将值转换为原始类型),该操作会调用 obj.valueOf() 以及(可能)obj.toString() 来完成此操作。
如果两个操作数都是字符串,则按字典顺序比较表示字符串 JavaScript 字符的 16 位代码单元(参见第 24 章)。
否则,将两个操作数都转换为数字,然后进行数值比较。
其他排序运算符的处理方式类似。

如果将 null 强制转换为数字,则它将变为 0:

数字(null)
0
5 + null
5

数字(未定义)
NaN
5 + 未定义
NaN

3 + ' 次'
'3 次'

字符串 (null)
'null'
字符串 (123.45)
'123.45'
字符串 (false)
'false'

Number({})
NaN ..为什么?算法:ToPrimitive()——将值转换为原始值。http ://speakingjs.com/es5/ch08.html

typeof 与 instanceof 与 {}.toString

https://javascript.info/instanceof
https://stackoverflow.com/questions/899574/which-is-best-to-use-typeof-or-instanceof

* typeof :返回描述值“类型”的字符串。 *

> typeof true
'boolean'
> typeof 'abc'
'string'
> typeof {} // empty object literal
'object'
> typeof [] // empty array literal
'object'

typeof undefined
'undefined'

typeof null
'object'

var a = null;

(!a && typeof a === "object"); // true
null is the only primitive value that is "falsy" 
but that also returns "object" from the typeof check.

Enter fullscreen mode Exit fullscreen mode

实际用途:
在 Jquery https://code.jquery.com/jquery-3.3.1.js

function isArrayLike( obj ) {

    // Support: real iOS 8.2 only (not reproducible in simulator)
    // `in` check used to prevent JIT error (gh-2145)
    // hasOwn isn't used here due to false negatives
    // regarding Nodelist length in IE
    var length = !!obj && "length" in obj && obj.length,
        type = toType( obj );

    if ( isFunction( obj ) || isWindow( obj ) ) {
        return false;
    }

    return type === "array" || length === 0 ||
        typeof length === "number" && length > 0 && ( length - 1 ) in obj;
}

Enter fullscreen mode Exit fullscreen mode
  • 实例

http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/

https://javascript.info/instanceof

instanceof 运算符本质上检查左侧对象的原型链中的任何内容是否与
右侧对象的原型属性所引用的对象相同。

var arr = [];
arr instanceof Array; // true
此语句返回true,因为 Array.prototype(右侧对象的原型属性)
引用了与左侧对象内部 [[Prototype]] 相同的对象([[Prototype]]在具有proto扩展的客户端中
通过 arr.proto“可见” )。 我之前提到的另一种构造函数检查通常如下所示:

var arr = [];
arr.constructor == 数组; // 真的

instanceof 运算符测试对象原型链中是否存在 constructor.prototype,即 Array.prototype。

Foo 的一个实例;// true

运算符 instanceof 的左操作数为一个普通对象,右操作数为一个函数。instanceof
回答的问题是:在 a 的整个 [[Prototype]] (即原型链)中,Foo.prototype 任意指向的对象是否出现过?

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof

http://speakingjs.com/es5/ch01.html#basic_prim_vs_obj
value instanceof Constr
如果 value 是由构造函数 Constr 创建的对象(参见构造函数:对象的工厂),则返回 true。以下是一些示例:

> var b = new Bar();  // object created by constructor Bar
> b instanceof Bar
true

> {} instanceof Object
true
> [] instanceof Array
true
> [] instanceof Object  // Array is a subconstructor of Object
true

> undefined instanceof Object
false
> null instanceof Object
false

Enter fullscreen mode Exit fullscreen mode

关于instanceof的问题

案例1:

function Rabbit() {}
let rabbit = new Rabbit();

// changed the prototype
Rabbit.prototype = {};
rabbit instanceof Rabbit //false
Enter fullscreen mode Exit fullscreen mode

这就是避免更改原型的原因之一。只是为了保证安全。

情况 2:
问题出现在多框架 DOM 环境中的脚本编写中。简而言之,在一个 iframe 中创建的数组对象不会与在另一个 iframe 中创建的数组共享 [[Prototype]]。它们的构造函数是不同的对象,因此 instanceof 和构造函数检查都会失败:

var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1,2,3); // [1,2,3]

// Boom!
arr instanceof Array; // false

// Boom!
arr.constructor === Array; // false


Enter fullscreen mode Exit fullscreen mode

Object toString 类型
// 为了方便起见,将 toString 方法复制到变量中


let objectToString = Object.prototype.toString;

// what type is this?
let arr = [];

alert( objectToString.call(arr) ); // [object Array]

Object.prototype.toString.call( [1,2,3] );
Object.prototype.toString.call( null );         // "[object Null]"
Object.prototype.toString.call( undefined );    // "[object Undefined]"

Enter fullscreen mode Exit fullscreen mode

对于数字,它将是 [object Number]
对于布尔值,它将是 [object Boolean]
对于 null:[object Null]
对于未定义:[object Undefined]
对于数组:[object Array]
...等等(可定制)。

我们可以看到,{}.toString 从技术上来说是一种“更高级”的 typeof。

函数

当前执行函数

  • 在 JavaScript 中使用 IIFE 来控制变量范围

http://speakingjs.com/es5/ch01.html#basic_prim_vs_obj
http://speakingjs.com/es5/ch16.html#iife

function f() {
    if (condition) {
        var tmp = ...;
        ...
    }
    // tmp still exists here
    // => not what we want
}

Enter fullscreen mode Exit fullscreen mode

如果你想为 then 块引入一个新的作用域,你可以定义一个函数并立即调用它。
这是一种变通方法,模拟了块级作用域:

function f() {
    if (condition) {
        (function () {  // open block
            var tmp = ...;
            ...
        }());  // close block
    }
}
Enter fullscreen mode Exit fullscreen mode

IIFE 变体:带有参数的 IIFE
您可以使用参数来定义 IIFE 内部的变量:

var x = 23;
(function (twice) {
    console.log(twice);
}(x * 2));
This is similar to:

var x = 23;
(function () {
    var twice = x * 2;
    console.log(twice);
}());
Enter fullscreen mode Exit fullscreen mode

IIFE 用例:通过闭包无意中共享
闭包保持与外部变量的连接,这有时不是您想要的:

var result = [];
for (var i=0; i < 5; i++) {
    result.push(function () { return i });  // (1)
}
console.log(result[1]()); // 5 (not 1)
console.log(result[3]()); // 5 (not 3)
The value returned in line (1) is always the current value of i, not the value it had when the function was created. After the loop is finished, i has the value 5, which is why all functions in the array return that value. If you want the function in line (1) to receive a snapshot of the current value of i, you can use an IIFE:

for (var i=0; i < 5; i++) {
    (function () {
        var i2 = i; // copy current i
        result.push(function () { return i2 });
    }());
}

Enter fullscreen mode Exit fullscreen mode

如何修正此功能?


var myAlerts = [];

for (var i = 0; i < 5; i++) {
    myAlerts.push(
        function inner() {
            alert(i);
        }
    );
}

myAlerts[0](); // 5
myAlerts[1](); // 5
myAlerts[2](); // 5
myAlerts[3](); // 5
myAlerts[4](); // 5


Answer :

var myAlerts = [];

for (var i = 0; i < 5; i++) {
    myAlerts.push(
       (function iife(){
         var j = i ;
         return function inner() {
            console.log(j);
          }
       })()

    );
}
myAlerts[1]()

Enter fullscreen mode Exit fullscreen mode

https://content.myemma.com/emmatech/using-iifes-in-javascript-to-control-variable-scope
https://stackoverflow.com/questions/2421911/what-is-the-purpose-of-wrapping-whole-javascript-files-in-anonymous-functions-li
https://stackoverflow.com/questions/13341698/javascript-plus-sign-in-front-of-function-name
https://stackoverflow.com/questions/8228281/what-is-the-function-construct-in-javascript
https://stackoverflow.com/questions/592396/what-is-the-purpose-of-a-self-executing-function-in-javascript

http://speakingjs.com/es5/ch01.html#basic_prim_vs_obj

  • *参数太多或太少*
function f(x, y) {
    console.log(x, y);
    return toArray(arguments);
}
Additional parameters will be ignored (except by arguments):

> f('a', 'b', 'c')
a b
[ 'a', 'b', 'c' ]

Enter fullscreen mode Exit fullscreen mode
  • *可选参数* 以下是为参数分配默认值的常见模式:
function pair(x, y) {
    x = x || 0;  // (1)
    y = y || 0;
    return [ x, y ];
}
In line (1), the || operator returns x if it is truthy (not null, undefined, etc.). Otherwise, it returns the second operand:

> pair()
[ 0, 0 ]
> pair(3)
[ 3, 0 ]
> pair(3, 5)
[ 3, 5 ]
Enter fullscreen mode Exit fullscreen mode
function pair(x, y) {
    if (arguments.length !== 2) {
        throw new Error('Need exactly 2 arguments');
    }
    ...
}
Enter fullscreen mode Exit fullscreen mode

-方法内的函数


var jane = {
    name: 'Jane',
    friends: [ 'Tarzan', 'Cheeta' ],
    logHiToFriends: function () {
        'use strict';
        this.friends.forEach(function (friend) {
            // `this` is undefined here
            console.log(this.name+' says hi to '+friend);
        });
    }
}
Calling logHiToFriends produces an error: why ?

> jane.logHiToFriends()
TypeError: Cannot read property 'name' of undefined

Ans :
 jane.logHiToFriends() runs like 

 var callback = function (friend) {
            // `this` is undefined here
            console.log(this.name+' says hi to '+friend);
        }

 var jane = {
    name: 'Jane',
    friends: [ 'Tarzan', 'Cheeta' ],
    logHiToFriends: function () {
        'use strict';
        this.friends.forEach(callback);
    }
}

as callback funs like callback() i.e without any context , this points to global object i.e window

Enter fullscreen mode Exit fullscreen mode

让我们看看解决这个问题的两种方法。首先,我们可以将其存储在另一个变量中:


logHiToFriends: function () {
    'use strict';
    var that = this;
    this.friends.forEach(function (friend) {
        console.log(that.name+' says hi to '+friend);
    });
}
Or, forEach has a second parameter that allows you to provide a value for this:

logHiToFriends: function () {
    'use strict';
    this.friends.forEach(function (friend) {
        console.log(this.name+' says hi to '+friend);
    }, this);
}

Enter fullscreen mode Exit fullscreen mode

呼叫、申请、绑定

https://www.smashingmagazine.com/2014/01/understanding-javascript-function-prototype-bind/

https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md

致电、申请、绑定 - 了解更多

var score = Function.prototype.call.bind(scoreCalculator.getScore); //绑定调用scoreCalculator.getScore
score(player1);

正在做这个

scoreCalculator.getScore.call(player1)

Enter fullscreen mode Exit fullscreen mode

并且您可以call从任何地方借用该方法,在本例中是从 Function.prototype 借用,但在哪里以及将其绑定到 getScore 函数并不重要。

称呼

使用调用:

inArray: function( elem, arr, i ) {
        return arr == null ? -1 : indexOf.call( arr, elem, i );
    }

Enter fullscreen mode Exit fullscreen mode
var elems = {
   length: 0,
   add: function(elem){
       Array.prototype.push.call(this, elem);
   },
   gather: function(id){
       this.add(document.getElementById(id));
   }
 };

 elems.gather("first");

 console.log(elems.length == 1 && elems[0].nodeType,
 "Verify that we have an element in our stash");

 elems.gather("second");

 console.log(elems.length == 2 && elems[1].nodeType,
 "Verify the other insertion"); 



Enter fullscreen mode Exit fullscreen mode

申请


 function smallest(array){
     return Math.min.apply(Math, array);
 }
 function largest(array){
     return Math.max.apply(Math, array);
 }

 assert(smallest([0, 1, 2, 3]) == 0,
 "Located the smallest value.");

 assert(largest([0, 1, 2, 3]) == 3,
 "Located the largest value."); 

Enter fullscreen mode Exit fullscreen mode

绑定

手动模拟构造函数的 apply()
我们可以分两步模拟 apply()。

步骤 1
通过方法调用将参数传递给 Date(它们尚未在数组中):

     new (Date.bind(null, 2011, 11, 24))

     or 
     new (Date.bind.call(Date,null, 2011, 11, 24))

Enter fullscreen mode Exit fullscreen mode

上述代码使用bind()创建一个没有参数的构造函数,并通过new调用它。

步骤 2
使用 apply() 将数组传递给 bind()。由于 bind() 是一个方法调用,因此我们可以使用 apply():

new (Function.prototype.bind.apply(
         Date, [null, 2011, 11, 24]))

Enter fullscreen mode Exit fullscreen mode

上述数组包含 null,后跟 arr 的元素。我们可以使用 concat() 通过在 arr 前面添加 null 来创建它:

var arr = [2011, 11, 24];
new (Function.prototype.bind.apply(
         Date, [null].concat(arr)))
Enter fullscreen mode Exit fullscreen mode

'use strict';
var jane = {
    name: 'Jane',

    describe: function () {
        return 'Person named '+this.name;
    }
};

Enter fullscreen mode Exit fullscreen mode

我们希望从 jane 中提取方法 describe,将其放入变量 func 中,然后调用它。但是,这样做行不通:

> var func = jane.describe;
> func()
TypeError: Cannot read property 'name' of undefined
The solution is to use the method bind() that all functions have. It creates a new function whose this always has the given value:

> var func2 = jane.describe.bind(jane);
> func2()
'Person named Jane'


Enter fullscreen mode Exit fullscreen mode
  • 如何删除函数
var animals = [
  { species: 'Lion', name: 'King' },
  { species: 'Whale', name: 'Fail' }
];

for (var i = 0; i < animals.length; i++) {
  (function(i) {
    this.print = function() {
      console.log('#' + i + ' ' + this.species
                  + ': ' + this.name);
    }
    this.print();
    this.print = null ;
    delete this.print ;
  }).call(animals[i], i);
}
Enter fullscreen mode Exit fullscreen mode
  • 实例失败

如果你有两个任意对象,比如 a 和 b,并且想要找出这两个对象是否通过 [[Prototype]] 链相互关联,那么单独的 instanceof 是无济于事的。

更简洁的,[[Prototype]] 反射方法是:


      function Foo() {  }

      Foo.prototype = { 
         c :2

       }; // create a new prototype object

      var a1 = new Foo();

      Foo.prototype.isPrototypeOf( a ); // true

Enter fullscreen mode Exit fullscreen mode

注意,在这种情况下,我们实际上并不关心(甚至不需要) Foo ,我们只需要一个对象(在我们的例子中,任意标记为 Foo.prototype)来与另一个对象进行测试。 isPrototypeOf(..) 回答的问题是:在 a 的整个 [[Prototype]] 链中,Foo.prototype 是否出现过?

https://github.com/getify/You-Dont-Know-JS/blob/6efd08c9db8e9808a9046204c719c99cb4702c18/this%20%26%20object%20prototypes/ch5.md#L487

let,const 箭头函数

https://github.com/nzakas/understandinges6/blob/master/manuscript/01-Block-Bindings.md
https://www.w3schools.com/js/js_arrow_function.asp

json.stringify

https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch4.md

严格的

http://speakingjs.com/es5/ch07.html#strict_mode
https://stackoverflow.com/questions/1335851/what-does-use-strict-do-in-javascript-and-what-is-the-reasoning-behind-it

对象中的 this

第 1 章:https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch1.md
第 2 章: https: //github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md

http://davidshariff.com/blog/javascript-this-keyword/

有效的 Javascript:第 4 章

this 的范围始终由其最近的封闭
函数决定。


function CSVReader(separators) {
    this.separators = separators || [","];
    this.regexp =
    new RegExp(this.separators.map(function(sep) {
      return "\\" + sep[0];
       }).join("|"));
}


CSVReader.prototype.read = function(str) {
    var lines = str.trim().split(/\n/);
    return lines.map(function(line) {
        console.log(this)
       return line.split(this.regexp); // wrong this!
     });
};
var reader = new CSVReader();
reader.read("a,b,c\nd,e,f\n");

Enter fullscreen mode Exit fullscreen mode

[
[
"a,b,c"
],
[
"d,e,f"
]
]


function CSVReader(separators) {
    this.separators = separators || [","];
    this.regexp =
    new RegExp(this.separators.map(function(sep) {
      return "\\" + sep[0];
       }).join("|"));
}


CSVReader.prototype.read = function(str) {
    var lines = str.trim().split(/\n/);
    return lines.map(function(line) {
        console.log(this)
       return line.split(this.regexp); // wrong this!
     },this);
};
var reader = new CSVReader();
reader.read("a,b,c\nd,e,f\n");

Enter fullscreen mode Exit fullscreen mode

[
[
"a",
"b",
"c"
],
[
"d",
"e",
"f"
]
]

闭包

注意:
作用域链仅适用于函数内部的函数,而不适用于对象内部的函数

      var StartStopCounter = {
          counter : 0,
          start : function(){
                StartStopCounter.stopCounter = setInterval(function(){
                    console.log(StartStopCounter.counter);
                    //que : why only counter won't work ?
                    StartStopCounter.counter=StartStopCounter.counter + 1 ;
                },1000);

          },
          stop : function(){
              clearInterval(StartStopCounter.stopCounter);

          }
      }


Enter fullscreen mode Exit fullscreen mode
  • 你不知道的 JS:作用域和闭包

https://github.com/getify/You-Dont-Know-JS/blob/master/up%20%26%20going/ch1.md#scope
https://github.com/getify/You-Dont-Know-JS/tree/master/scope%20%26%20closures )

http://javascript.info/closure

有时,封装用于限制
某些元素的可见性,这种行为称为数据隐藏。JavaScript 的对象系统不
提供直接隐藏数据的方法,因此使用一种称为闭包的方法来实现数据隐藏。

通过使用涉及闭包的函数技术,您可以实现
与大多数面向对象语言提供的功能一样有效的数据隐藏

https://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript

  • 闭包示例的实际使用

ex1:私有变量


      function Ninja() {                                            //#1

        var feints = 0;                                             //#2

        this.getFeints = function(){                                //#3
          return feints;                                            //#3
        };                                                          //#3

        this.feint = function(){                                    //#4
          feints++;                                                 //#4
        };                                                          //#4
      }

      var ninja = new Ninja();                                      //#5

      ninja.feint();                                                //#6

      assert(ninja.feints === undefined,                            //#7
          "And the private data is inaccessible to us." );          //#7

      assert(ninja.getFeints() == 1,                                //#8
             "We're able to access the internal feint count." );    //#8

Enter fullscreen mode Exit fullscreen mode

示例2:


function animateIt(elementId) {

    var elem = document.getElementById(elementId);              //#2
    var tick = 0;                                               //#3

    var timer = setInterval(function(){                         //#4
      if (tick < 100) {
        elem.style.left = elem.style.top = tick + "px";
        tick++;
      }
      else {
        clearInterval(timer);
        assert(tick == 100,                                      //#5
               "Tick accessed via a closure.");
        assert(elem,
               "Element also accessed via a closure.");
        assert(timer,
               "Timer reference also obtained via a closure." );
      }
    }, 10);

  }

  animateIt('box')

Enter fullscreen mode Exit fullscreen mode

例 3:

const createStore = (reducer) => {
let state;
let listeners = [];

const getState = () => 状态;

const dispatch = (action) => {
state = reducer(state, action)
listeners.forEach(listener => listener());
};

const subscribe = (listener) => {
listeners.push(listener);
return () => {
listeners = listeners.filter(l => l !== listener);
}
};

dispatch({}); // 虚拟调度

返回 { getState, dispatch, subscribe };

};

闭包使用示例:重载函数


 var ninjas = {
    values: ["Dean Edwards", "Sam Stephenson", "Alex Russell"]
 };

function addMethod(object, name, fn) {
 var old = object[name];
 object[name] = function(){
   if (fn.length == arguments.length)
      return fn.apply(this, arguments)
   else if (typeof old == 'function')
      return old.apply(this, arguments);
  };
}

 addMethod(ninjas, "find", function(){
          return this.values;
 });

 addMethod(ninjas, "find", function(name){
      var ret = [];
      for (var i = 0; i < this.values.length; i++)
      if (this.values[i].indexOf(name) == 0)
      ret.push(this.values[i]);
      return ret;
 });

 addMethod(ninjas, "find", function(first, last){
      var ret = [];
      for (var i = 0; i < this.values.length; i++)
      if (this.values[i] == (first + " " + last))
      ret.push(this.values[i]);
      return ret;
 });

 assert(ninjas.find().length == 3,
 "Found all ninjas");
 assert(ninjas.find("Sam").length == 1,
 "Found ninja by first name");
 assert(ninjas.find("Dean", "Edwards").length == 1,
 "Found ninja by first and last name");
 assert(ninjas.find("Alex", "Russell", "Jr") == 
 ,
 "Found nothing");

Enter fullscreen mode Exit fullscreen mode

示例 2:
创建一个独立范围

考虑以下代码片段:


(function(){
 var numClicks = 0;
 document.addEventListener("click", function(){
 alert( ++numClicks );
 }, false);
})();

/*
Because the immediate function is executed immediately (hence its name), the click
handler is also bound right away. The important thing to note is that a closure is created
for the handler that includes numClicks, allowing the numClicks variable to persist
along with the handler, and be referenceable by the handler but nowhere else.
 This is one of the most common ways in which immediate functions are used: as
simple, self-contained wrappers for functionality. The variables needed for the unit of
functionality are trapped in the closure, but they aren’t visible anywhere else.
*/
Enter fullscreen mode Exit fullscreen mode

目的

http://speakingjs.com/es5/ch17.html
https://stackoverflow.com/questions/tagged/javascript+object

复制对象
要创建对象的相同副本,您需要正确完成两件事:

副本必须与原始对象具有相同的原型(参见第 2 层:对象之间的原型关系)。
副本必须具有与原始对象相同的属性。
以下函数执行此类复制:

function copyObject(orig) {
// 1. copy 与 orig 具有相同的原型
var copy = Object.create(Object.getPrototypeOf(orig));

// 2. copy has all of orig’s properties
copyOwnPropertiesFrom(copy, orig);

return copy;
Enter fullscreen mode Exit fullscreen mode

通过此函数
将属性从 orig 复制到 copy:

function copyOwnPropertiesFrom(target, source) {
Object.getOwnPropertyNames(source) // (1)
.forEach(function(propKey) { // (2)
var desc = Object.getOwnPropertyDescriptor(source, propKey); // (3)
Object.defineProperty(target, propKey, desc); // (4)
});
return target;
};
所涉及的步骤如下:

获取一个包含源对象所有自有属性键的数组。
迭代这些键。
检索属性描述符。
使用该属性描述符在目标对象中创建自有属性。

https://stackoverflow.com/questions/3390396/how-to-check-for-undefined-in-javascript

如果删除该属性,其键也会消失:

delete obj.foo
true
Object.keys(obj)
[ 'bar' ]
删除操作仅影响对象的直接(“自身”而非继承)属性。其原型不受影响

  • 如果仅将属性设置为未定义,则该属性仍然存在,并且对象仍然包含其键

var obj = { foo: 'a', bar: 'b' };

obj.foo = undefined;
Object.keys(obj)
[ 'foo', 'bar' ]

https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch5.md


      'use strict';

      const anotherObject = {};

      Object.defineProperty(anotherObject, 'a', {
        value: 2,
        writable: false
      });

      var myObject = Object.create( anotherObject );

      myObject.a = 3;

Enter fullscreen mode Exit fullscreen mode

https://medium.freecodecamp.org/lets-explore-objects-in-javascript-4a4ad76af798


function SuperType(name){
 this.name = name;
 this.colors = ["red","green"];
}

SuperType.prototype.sayName = function(){
 console.log(this.name);
};

function SubType(name, age){

 //inherit properties
 SuperType.call(this, name);

 this.age = age;
}

//inherit methods
SubType.prototype = new SuperType();  // problem as this creates color property on prototype 

SubType.prototype.sayAge = function(){
 console.log(this.age);
};

var instance1 = new SubType("Nicholas", 29);


problems with this :

console.log(instance1) > color property on prototype 

SubType {name: "Nicholas", colors: Array(2), age: 29}
    age: 29
    colors: (2) ["red", "green"]
    name: "Nicholas"
    __proto__: SuperType
        colors: (2) ["red", "green"]
        name: undefined
        sayAge: ƒ ()
        __proto__: Object

Enter fullscreen mode Exit fullscreen mode

https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch5.md
https://stackoverflow.com/questions/310870/use-of-prototype-vs-this-in-javascript
https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch6.md
https://stackoverflow.com/questions/9959727/proto-vs-prototype-in ​​-javascript
https://stackoverflow.com/questions/4166616/understanding-the-difference-between-object-create-and-new-somefunction
https://stackoverflow.com/questions/4508313/advantages-of-using-prototype-vs-defining-methods-straight-in-the-constructor
https://stackoverflow.com/questions/10430279/extending-an-object-in-javascript
https://stackoverflow.com/questions/3781373/javascript-what-are-extend-and-prototype-used-for
https://stackoverflow.com/questions/14034180/why-is-extending-native-objects-a-bad-practice
https://stackoverflow.com/questions/4740806/native-way-to-merge-objects-in-javascript
https://stackoverflow.com/questions/8859828/javascript-what-dangers-are-in-extending-array-prototype

使用 hasOwnProperty 防止原型污染

var dict = {};
"alice" in dict; // false
"bob" in dict; // false
"chris" in dict; // false
"toString" in dict; // true
"valueOf" in dict; // true
Luckily, Object.prototype provides the hasOwnProperty method, which
is just the tool we need to avoid prototype pollution when testing for
dictionary entries:
dict.hasOwnProperty("alice"); // false
dict.hasOwnProperty("toString"); // false
dict.hasOwnProperty("valueOf"); // false

Enter fullscreen mode Exit fullscreen mode

获取所有属性

https://javascript.info/getting-all-properties
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries

Object.values() 方法返回给定对象自己的可枚举属性值的数组,
其顺序与 for...in 循环提供的顺序相同(不同之处在于 for-in 循环
也枚举原型链中的属性)。

Object.keys(obj) / Object.values(obj) / Object.entries(obj)
这些方法仅列出可枚举属性,以及那些以字符串作为键的属性。1
)Object.keys(Object.prototype)

[]
Object.keys() 方法返回给定对象自己的属性名称的数组,其
顺序与我们通过正常循环获得的顺序相同。

2)Object.getOwnPropertyNames(Object.prototype)
- 返回所有自己的字符串属性名称的数组
如果我们想要不可枚举的属性:

(12) ["constructor", "__defineGetter__", "__defineSetter__", "hasOwnProperty", "__lookupGetter__", "__lookupSetter__", "isPrototypeOf", "propertyIsEnumerable", "toString", "valueOf", "__proto__", "toLocaleString"]
Enter fullscreen mode Exit fullscreen mode

3)Reflect.ownKeys(Object.prototype)
(12) ["构造函数"," defineGetter "," defineSetter ","hasOwnProperty"," lookupGetter "," lookupSetter ","isPrototypeOf","propertyIsEnumerable","toString","valueOf"," proto ","toLocaleString"]

https://stackoverflow.com/questions/15283720/why-are-for-in-faster-than-for-loops-when-looping-through-an-array
如果在数组中找不到属性,for 循环也会在 [[Prototype]] 链上搜索。例如,在 [0,,2] 上循环会从 1 开始一直搜索到 Object.prototype[[Prototype]]。

不要使用 for..in 循环数组。永远不要。

手动模拟构造函数的 apply()

1) 通过方法调用将参数传递给 Date(它们目前还不在数组中):

新的(Date.bind(null,2011,11,24))

上述代码使用bind()创建一个没有参数的构造函数,并通过new调用它。

2)
使用apply()将数组传递给bind()。因为bind()是一个方法调用,所以我们可以使用apply():

new (Function.prototype.bind.apply(
Date, [null, 2011, 11, 24]))
上述数组包含 null ,后跟 arr 的元素。我们可以使用 concat() 通过在 arr 前面添加 null 来创建它:

var arr = [2011, 11, 24];
new (Function.prototype.bind.apply(
Date, [null].concat(arr)))

有效的 Javascript - 第四章

使用默认构造函数的问题

http://raganwald.com/2014/07/09/javascript-constructor-problem.html

https://javascript.info/function-prototype


function Rabbit() {}

/* default prototype
Rabbit.prototype = { constructor: Rabbit };
*/

Enter fullscreen mode Exit fullscreen mode

function Rabbit() {}
// by default:
// Rabbit.prototype = { constructor: Rabbit }

alert( Rabbit.prototype.constructor == Rabbit ); // true

Enter fullscreen mode Exit fullscreen mode

...JavaScript 本身并不能确保正确的“构造函数”值。

是的,它存在于函数的默认“原型”中,但仅此而已。之后会发生什么,完全取决于我们。

具体来说,如果我们整体替换默认原型,那么其中就不会有“构造函数”。

例如:

function Rabbit() {}
Rabbit.prototype = {
  jumps: true
};

let rabbit = new Rabbit();
alert(rabbit.constructor === Rabbit); // false

Enter fullscreen mode Exit fullscreen mode

因此,为了保留正确的“构造函数”,我们可以选择向默认“原型”添加/删除属性,而不是将其全部覆盖:

function Rabbit() {}
Enter fullscreen mode Exit fullscreen mode

// 不完全覆盖 Rabbit.prototype
// 只需添加到其中

Rabbit.prototype.jumps = true
Enter fullscreen mode Exit fullscreen mode

// 保留默认的 Rabbit.prototype.constructor
或者,手动重新创建构造函数属性:

Rabbit.prototype = {
  jumps: true,
  constructor: Rabbit
};
Enter fullscreen mode Exit fullscreen mode

// 现在构造函数也是正确的,因为我们添加了它

    function Person(){

    }

    var friend = new Person();

    Person.prototype = {
     name : "Nicholas",
     age : 29,
     job : "Software Engineer",
     sayName : function () {
        console.log(this.name);
       }
    };


Constructor is Object Constructor
(new Person()).constructor
ƒ Object() { [native code] }

Enter fullscreen mode Exit fullscreen mode

数组

https://javascript.info/array-methods
http://speakingjs.com/es5/ch18.html
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
https://stackoverflow.com/questions/tagged/arrays+javascript

拼接
https://javascript.info/array-methods#splice
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice


array.splice(start[, deleteCount[, item1[, item2[, ...]]]]) //deletecount is no of element to delete

1)
let arr = ["I", "study", "JavaScript"];

arr.splice(1, 1); // from index 1 remove 1 element

alert( arr ); // ["I", "JavaScript"]

2)
let arr = ["I", "study", "JavaScript", "right", "now"];

// remove 3 first elements and replace them with another
arr.splice(0, 3, "Let's", "dance");

alert( arr ) // now ["Let's", "dance", "right", "now"]

3)
let arr = ["I", "study", "JavaScript"];

// from index 2
// delete 0
// then insert "complex" and "language"
arr.splice(2, 0, "complex", "language");

alert( arr ); // "I", "study", "complex", "language", "JavaScript"
Enter fullscreen mode Exit fullscreen mode

https://github.com/deenjohn/Javascript-revision/blob/master/General/arraylike%20vs%20array.md

究竟是什么让一个对象“像数组”?数组对象的基本契约
归结为两个简单的规则。
■ 它有一个范围在 0...232 – 1 的整数 length 属性。
■ length 属性大于对象的最大索引。
索引是一个范围在 0...232 – 2 的整数,其字符串表示形式是对象属性的键。

这就是对象需要实现的所有行为,以便
与 Array.prototype 的任何方法兼容。即使是一个简单的对象字面量,也可以用来创建类似数组的对象:


var arrayLike = { 0: "a", 1: "b", 2: "c", length: 3 };
var result = Array.prototype.map.call(arrayLike, function(s) {
return s.toUpperCase();
}); // ["A", "B", "C"]


function toArray(arrayLikeObject) {
    return Array.prototype.slice.call(arrayLikeObject);
}

Enter fullscreen mode Exit fullscreen mode

字符串的行为也类似于不可变数组,因为它们可以被索引
,并且其长度可以通过 length 属性访问。因此,
Array.prototype 中不修改数组的方法也可以用于
字符串:

var result = Array.prototype.map.call("abc", function(s) {
return s.toUpperCase();
}); // ["A", "B", "C"]


Enter fullscreen mode Exit fullscreen mode

只有一个 Array 方法不是完全泛型的:数组连接方法 concat。此方法可以在任何类似数组的接收器上调用,但它会测试其参数的 [[Class]]。如果参数
是真正的数组,则其内容将连接到结果中;否则,
该参数将作为单个元素添加。这意味着,例如,
我们不能简单地将数组与
参数对象的内容连接起来:


function namesColumn() {
  return ["Names"].concat(arguments);
}
namesColumn("Alice", "Bob", "Chris");
// ["Names", { 0: "Alice", 1: "Bob", 2: "Chris" }]


Enter fullscreen mode Exit fullscreen mode

为了让 concat 将一个类数组对象视为真正的
数组,我们必须自己进行转换。一个流行且简洁的
转换方法是调用类数组
对象的 slice 方法:


function namesColumn() {
   return ["Names"].concat([].slice.call(arguments));
}
namesColumn("Alice", "Bob", "Chris");
// ["Names", "Alice", "Bob", "Chris"]


Enter fullscreen mode Exit fullscreen mode

https://stackoverflow.com/questions/2218999/remove-duplicates-from-an-array-of-objects-in-javascript

DOM

问:http://javascript.info/task/select-diagonal-cells
答:


    var tr = Array.from(document.querySelectorAll('tr'));
    for(var i =0 ;i<tr.length ;i++){
       for(var j =0 ;j<tr.length ;j++){
         if(i ==j){
           console.log("i ",i ,j);
           console.log((Array.from(tr[i].querySelectorAll('td'))[i]).style.background ='red');
           console.log('.......')
         }      
       }
    }

    // your code

Enter fullscreen mode Exit fullscreen mode
  • 现场收藏

所有 getElementsBy* 方法都会返回一个实时集合。此类集合始终反映文档的当前状态,
并在文档发生变化时“自动更新”。

http://javascript.info/searching-elements-dom#live-collections

适合快速查看 JavaScript 中的所有事件

https://www.w3schools.com/jsref/obj_event.asp

https://www.w3.org/TR/uievents/#widl-MouseEvent-relatedTarget

https://www.w3schools.com/js/js_events.asp

https://www.w3schools.com/jsref/event_cancelable.asp

https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html

https://github.com/krasimir/EventBus
https://stackoverflow.com/questions/2863547/javascript-scroll-event-for-iphone-ipad

http://javascriptkit.com/javatutors/touchevents.shtml

https://stackoverflow.com/questions/31865416/what-is-the-difference-between-event-target-event-toelement-and-event-srcelemen

var pressTimer;
document.getElementById("demo").addEventListener("mousedown", mouseDown);
document.getElementById("demo").addEventListener("mouseup", mouseUp);

function mouseDown() {
pressTimer = window.setTimeout(function() {
document.getElementById("demo").innerHTML = "鼠标按钮被按下。";
},1000);

}

函数 mouseUp() {
clearTimeout(pressTimer);
}

https://javascript.info/task/sliding-tree


var el = document.getElementById('tree');
console.log(el);
el.addEventListener("click", handler);

function handler(e){
  if(e.target.children.length == 1){
    e.target.children[0].hidden = !e.target.children[0].hidden;
  }
}

Enter fullscreen mode Exit fullscreen mode

mouseleave 与 mouseover 对比
https://codepen.io/deen_john/pen/jONJwJz?editors=0010
https://www.youtube.com/watch?v=pzT4hAY82q4

Safari 4、Android 2.2 WebKit 和 Opera Mobile 11 均具有以下行为:

1) touchstart 事件上的 preventDefault 可防止滚动、双击缩放和 mouseup/mousedown/click 事件。

2)touchmove 事件上的 preventDefault 阻止滚动。

3) touchend 事件上的 preventDefault 不会阻止滚动或鼠标事件。

4) 这些都无法阻止捏合缩放。Safari 实现了一个单独的“gesturechange”事件,该事件在捏合手势时触发,可用于阻止缩放。Android 和 Opera 均未实现此事件。

例子 :


<!DOCTYPE html>
<html>
<body>

<h1>Show checkboxes:</h1>

<form action="/action_page.php">
  <input type="checkbox" name="vehicle1" value="Bike"> I have a bike<br>
  <input type="checkbox" name="vehicle2" value="Car"> I have a car<br>
  <input type="checkbox" name="vehicle3" value="Boat" checked> I have a boat<br><br>
  <input type="submit" value="Submit">
</form>

<script>
var fe = document.querySelector('form');

fe.addEventListener("mousedown", function(e){
  console.log(e);
  e.preventDefault()
});

fe.addEventListener("mouseup", function(e){
e.preventDefault()
  console.log(e)
});

fe.addEventListener("click", function(e){
e.preventDefault()
  console.log(e)
});


</script>
</body>
</html>

Enter fullscreen mode Exit fullscreen mode

<body>

<p>This example uses the addEventListener() method to attach a "mousedown" and "mouseup" event to a p element.</p>

<p id="demo">Click me.</p>

<script>
document.getElementById("demo").addEventListener("mousedown", mouseDown);
document.getElementById("demo").addEventListener("mouseup", mouseUp);

function mouseDown(e) {
e.preventDefault();
//return false ;
 // document.getElementById("demo").innerHTML = "The mouse button is held down.";
}

function mouseUp(e) {
e.preventDefault();
//return false
  //document.getElementById("demo").innerHTML = "You released the mouse button.";
}
</script>

</body>

Enter fullscreen mode Exit fullscreen mode

在上面的例子中,事件顺序为 mousedown > mouseup > click
preventdefault 仅在点击时起作用

被动处理程序
https://javascript.info/default-browser-action#the-passive-handler-option

元素.closest()


$(document).on('click', function(event) {
  if (!$(event.target).closest('#menucontainer').length) {
    // Hide the menus.
  }
});

Enter fullscreen mode Exit fullscreen mode

上述处理程序会监听文档上的点击事件,并检查事件目标是否
为 #menucontainer 或是否以 #menucontainer 为父级。如果不是,则表明点击源自
#menucontainer 之外,因此如果菜单可见,则可以将其隐藏。

https://developer.mozilla.org/en-US/docs/Web/API/Element/closest

如果bubbles属性设置为false,则取消bubble
,跳过冒泡阶段


<body>

<p>Click the button to find out if the onclick event is a bubbling event.</p>

<button id ='button'>Try it</button>

<p id="demo"></p>

<script>

document.addEventListener("click", myFunction1);
button.addEventListener("click", myFunction1);
button.addEventListener("click", myFunction2);

function myFunction1() {
  console.log(event.cancelBubble);
  console.log('event ',  event.currentTarget)
  event.cancelBubble=true;
  document.getElementById("demo").innerHTML = event.cancelBubble;
}

function myFunction2(event) { 

  console.log('event ',  event.currentTarget)
  console.log(event.cancelBubble);

  document.getElementById("demo").innerHTML = event.cancelBubble;
}
</script>

</body>

Enter fullscreen mode Exit fullscreen mode

https://www.html5rocks.com/en/mobile/touchandmouse/
https://www.w3.org/TR/uievents/#events-mouseevent-event-order
https://www.w3.org/TR/uievents

Focus 事件:
在触发 Focus 事件之前,先触发 mousedown 事件。let
Mousedown > Focus

textContent 获取所有元素的内容,包括和

文章来源:https://dev.to/deen_john/resources-to-master-javascript-3d0p
PREV
VSCode 无需扩展即可实现的 4 件事
NEXT
使用函数式 JavaScript 验证信用卡号 Dolla Dolla Bill,你们好