掌握 JavaScript 的资源
掌握 Javascript
掌握 Javascript
Javascript 基础知识阅读:
http://dmitrysoshnikov.com/category/ecmascript/
-
MDN
https://developer.mozilla.org/bm/docs/Web/JavaScript)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference -
表达式和运算符
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators )
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.
单个“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
-
真值
https://developer.mozilla.org/en-US/docs/Glossary/Truthy
http://speakingjs.com/es5/ch01.html#basic_prim_vs_obj -
如何在 JavaScript 中检查“未定义”?
https://stackoverflow.com/questions/9959727/proto-vs-prototype-in -javascript )
https://stackoverflow.com/questions/27509/detecting-an-undefined-object-property)
-
JavaScript 数据类型和数据结构
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures ) -
parseInt() 和 Number() 之间有什么区别?
https://stackoverflow.com/questions/4090518/what-is-the-difference-between-parseint-and-number
嗯,它们在语义上是不同的,作为函数调用的 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
-
掌握 JavaScript 面试:什么是函数组合?
https://medium.com/javascript-scene/master-the-javascript-interview-what-is-function-composition-20dfb109a1a0#.i84zm53fb ) -
如何在 JavaScript 中检查数字是否为 NaN?
https://stackoverflow.com/questions/2652319/how-do-you-check-that-a-number-is-nan-in-javascript
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
因此我们可以使用如果要检查一个值是否为 NaN,则必须使用全局函数 isNaN():
> isNaN(NaN)
true
> isNaN(33)
false
但是 :
isNaN 函数无法正确处理非数字,因为它会先将非数字转换为数字。这种转换可能会产生 NaN,然后函数会错误地返回 true:
> isNaN('xyz')
true
因此,最好将 isNaN 与类型检查结合起来:
function myIsNaN(value) {
return typeof value === 'number' && isNaN(value);
}
或者,你可以检查该值是否不等于其自身(因为 NaN 是唯一具有此特征的值)。但这不太容易理解:
function myIsNaN(value) {
return value !== value;
}
- Number.IsNaN() 是否比 isNaN() 更不完善? https://stackoverflow.com/questions/25176459/is-number-isnan-more-broken-than-isnan
isNaN() 和 Number.isNaN() 都用于测试一个值是否为 NaN 值(或者,在 isNaN() 的情况下,可以将其转换为表示 NaN 值的数字类型值)。换句话说,“NaN”并非简单地表示“这个值不是数字”,而是具体表示“根据 IEEE-754,这个值是一个非数字类型的数值”。
上述所有测试都返回 false 的原因是因为所有给定的值都可以转换为非 NaN 的数值:
Number('') // 0
Number(' ') // 0
Number(true) // 1
Number(false) // 0
Number([0]) // 0
isNaN() 之所以“失效”,表面上是因为在测试值时不应该进行类型转换。而 Number.isNaN() 正是为此而设计的。具体来说,只有当值是数字类型时,Number.isNaN() 才会尝试将其与 NaN 进行比较。任何其他类型都会返回 false,即使它们字面上“不是数字”,因为 NaN 值的类型就是数字。请参阅 isNaN() 和 Number.isNaN() 各自的 MDN 文档。
如果您只是想确定某个值是否属于数字类型,即使该值是 NaN,也可以使用 typeof:
typeof 'RAWRRR' === 'number' // false
- null 与 undefined https://basarat.gitbooks.io/typescript/docs/javascript/null-undefined.html https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#Loose_equality_using
某些内容尚未初始化:undefined。
某些内容当前不可用:null。
-
为什么 null 是一个对象,以及 null 和 undefined 之间有什么区别?
https://stackoverflow.com/questions/801032/why-is-null-an-object-and-whats-the-difference-between-null-and-undefined )
https://stackoverflow.com/questions/5076944/what-is-the-difference-between-null-and-undefined-in-javascript?noredirect=1&lq=1 )
https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch1.md )
https://stackoverflow.com/questions/2559318/how-to-check-for-an-undefined-or-null-variable-in-javascript
https://stackoverflow.com/questions/5515310/is-there-a-standard-function-to-check-for-null-undefined-or-blank-variables-in
https://stackoverflow.com/questions/2647867/how-to-determine-if-variable-is-undefined-or-null
https://stackoverflow.com/questions/27509/detecting-an-undefined-object-property?noredirect=1&lq=1
https://stackoverflow.com/questions/4186906/check-if-object-exists-in-javascript
https://stackoverflow.com/questions/16672743/javascript-null-check
https://stackoverflow.com/questions/5716976/javascript-undefined-vs-void-0
https://stackoverflow.com/questions/385960/javascript-identify-whether-a-property-is-defined-and-set-to-undefined-or-u -
测试 null
https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch1.md )
如果要使用其类型测试空值,则需要一个复合条件:
var a = null;
(!a && typeof a === "object"); // true
When you’re 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
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
-
null 与零
https://javascript.info/comparison#strange-result-null-vs-0 -
ToBoolean
https://javascript.info/type-conversions#toboolean -
parseInt 和 parseFloat
使用加号 + 或 Number() 进行的数字转换非常严格。如果值不是精确的数字,转换会失败:
alert( +"100px" ); // NaN
在某些情况下,parseInt/parseFloat 会返回 NaN。这种情况发生在无法读取任何数字时:
alert( parseInt('a123') ); // NaN,第一个符号停止进程
- 二元逻辑运算符 http://speakingjs.com/es5/ch01.html#basic_prim_vs_obj https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch4.md#operators--and-
与 (&&)
如果第一个操作数为假,则返回它。否则,返回第二个操作数:
> 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;
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;
};
}
-
*字符串连接,二进制 + *
https://javascript.info/operators#string-concatenation-binary -
第 2 章 变量作用域
摘自书籍:《Effective JavaScript:68 种驾驭 JavaScript 力量的具体方法》
本章让我了解了更多有关闭包和范围的隐藏知识。
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) ...
上述代码检查 x 是否为 123 或 '123'。同样,这非常简洁,而且最好还是明确一点:
if (Number(x) === 123)
用例:将包装器实例与原语进行比较
Lenient equals 允许您将原语与包装的原语进行比较:
> 'abc' == new String('abc')
true
反对这种方法的理由有三个。首先,宽松的相等性在包装的原语之间不起作用:
> 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')
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 )) {
// ..
}
Object.is
https://javascript.info/number
这个表达式是如何求值的?x < y *算法
( http://speakingjs.com/es5/ch08.html#toprimitive)https://javascript.info/object-toprimitive
你评估一下比较:
x < y
通过采取以下步骤:
确保两个操作数都是原始类型。对象 obj 通过内部操作 ToPrimitive(obj, Number) 转换为原始类型(参见算法:ToPrimitive()——将值转换为原始类型),该操作会调用 obj.valueOf() 以及(可能)obj.toString() 来完成此操作。
如果两个操作数都是字符串,则按字典顺序比较表示字符串 JavaScript 字符的 16 位代码单元(参见第 24 章)。
否则,将两个操作数都转换为数字,然后进行数值比较。
其他排序运算符的处理方式类似。
-
第四章:强制转换
https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch4.md )
https://stackoverflow.com/questions/154059/how-to-check-empty-undefined-null-string-in-javascript -
第 3 条:警惕隐式强制转换
https://www.safaribooksonline.com/library/view/effective-javascript-68/9780132902281/ch01.html#ch01lev1sec3 )
如果将 null 强制转换为数字,则它将变为 0:
数字(null)
0
5 + null
5数字(未定义)
NaN
5 + 未定义
NaN3 + ' 次'
'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.
实际用途:
在 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;
}
- 实例
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
关于instanceof的问题
案例1:
function Rabbit() {}
let rabbit = new Rabbit();
// changed the prototype
Rabbit.prototype = {};
rabbit instanceof Rabbit //false
这就是避免更改原型的原因之一。只是为了保证安全。
情况 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
- {}.toString https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch3.md#internal-class
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]"
对于数字,它将是 [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
}
如果你想为 then 块引入一个新的作用域,你可以定义一个函数并立即调用它。
这是一种变通方法,模拟了块级作用域:
function f() {
if (condition) {
(function () { // open block
var tmp = ...;
...
}()); // close block
}
}
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);
}());
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 });
}());
}
如何修正此功能?
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]()
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' ]
- *可选参数* 以下是为参数分配默认值的常见模式:
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 ]
- 函数长度与参数 https://github.com/deenjohn/Javascript-revision/blob/master/General/Function%20length%20vs%20arguments ) 强制参数数量 如果要强制参数数量(特定数量的参数),可以检查arguments.length:
function pair(x, y) {
if (arguments.length !== 2) {
throw new Error('Need exactly 2 arguments');
}
...
}
-方法内的函数
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
让我们看看解决这个问题的两种方法。首先,我们可以将其存储在另一个变量中:
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);
}
呼叫、申请、绑定
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)
并且您可以call
从任何地方借用该方法,在本例中是从 Function.prototype 借用,但在哪里以及将其绑定到 getScore 函数并不重要。
-
使用自定义接收器调用方法
https://www.safaribooksonline.com/library/view/effective-javascript-68/9780132902281/ch03.html#ch03lev1sec3 ) -
使用 apply 调用具有不同数量参数的函数
https://www.safaribooksonline.com/library/view/effective-javascript-68/9780132902281/ch03.html#ch03lev1sec4 ) -
使用 bind 提取具有固定接收器的方法
https://www.safaribooksonline.com/library/view/effective-javascript-68/9780132902281/ch03.html#ch03lev1sec9 )
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
称呼
使用调用:
inArray: function( elem, arr, i ) {
return arr == null ? -1 : indexOf.call( arr, elem, i );
}
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");
申请
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.");
绑定
手动模拟构造函数的 apply()
我们可以分两步模拟 apply()。
步骤 1
通过方法调用将参数传递给 Date(它们尚未在数组中):
new (Date.bind(null, 2011, 11, 24))
or
new (Date.bind.call(Date,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)))
'use strict';
var jane = {
name: 'Jane',
describe: function () {
return 'Person named '+this.name;
}
};
我们希望从 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'
- 如何删除函数
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);
}
- 实例失败
如果你有两个任意对象,比如 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
注意,在这种情况下,我们实际上并不关心(甚至不需要) Foo ,我们只需要一个对象(在我们的例子中,任意标记为 Foo.prototype)来与另一个对象进行测试。 isPrototypeOf(..) 回答的问题是:在 a 的整个 [[Prototype]] 链中,Foo.prototype 是否出现过?
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");
[
[
"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");
[
[
"a",
"b",
"c"
],
[
"d",
"e",
"f"
]
]
-
JavaScript 中的借用方法
http://davidshariff.com/blog/borrowing-methods-in-javascript/#first-article ) -
JavaScript 中的执行上下文和堆栈是什么?
http://davidshariff.com/blog/what-is-the-execution-context-in-javascript/#first-article ) -
标识符解析、执行上下文和作用域链
http://jibbering.com/faq/notes/closures/#clIRExSc )
闭包
- JavaScript 作用域链中的标识符解析和闭包 http://davidshariff.com/blog/javascript-scope-chain-and-closures/ )
注意:
作用域链仅适用于函数内部的函数,而不适用于对象内部的函数
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);
}
}
- 你不知道的 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
示例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')
例 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");
示例 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.
*/
目的
http://speakingjs.com/es5/ch17.html
https://stackoverflow.com/questions/tagged/javascript+object
-
MDN:对象
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object ) -
在 JavaScript 中深度克隆对象的最有效方法是什么?
https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript ?rq=1 )
复制对象
要创建对象的相同副本,您需要正确完成两件事:
副本必须与原始对象具有相同的原型(参见第 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;
通过此函数
将属性从 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;
};
所涉及的步骤如下:
获取一个包含源对象所有自有属性键的数组。
迭代这些键。
检索属性描述符。
使用该属性描述符在目标对象中创建自有属性。
-
JavaScript 对象的长度
https://stackoverflow.com/questions/5223/length-of-a-javascript-object?rq=1 ) -
如何动态合并两个 JavaScript 对象的属性?
https://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically? rq= 1 ) -
检测未定义的对象属性
https://stackoverflow.com/questions/27509/detecting-an-undefined-object-property?rq=1 ) -
如何从 JavaScript 对象中删除属性?
https://stackoverflow.com/questions/208105/how-do-i-remove-a-property-from-a-javascript-object ?rq= 1 ) -
如何从 JavaScript 对象中删除属性?
https://stackoverflow.com/questions/208105/how-do-i-remove-a-property-from-a-javascript-object ) -
检查对象是否为数组?
https://stackoverflow.com/questions/4775722/check-if-object-is-array ) -
如何在 JavaScript 中检查对象是否具有属性?
https://stackoverflow.com/questions/135448/how-do-i-check-if-an-object-has-a-property-in-javascript ) -
如何在 JavaScript 中检查对象是否具有键?
https://stackoverflow.com/questions/455338/how-do-i-check-if-an-object-has-a-key-in-javascript ?noredirect=1&lq= 1 )
https://stackoverflow.com/questions/3390396/how-to-check-for-undefined-in-javascript)
-
检查 JavaScript 对象中是否存在某个键?
https://stackoverflow.com/questions/1098040/checking-if-a-key-exists-in-a-javascript-object ) -
如何从 JavaScript 对象中删除属性?
https://stackoverflow.com/questions/208105/how-do-i-remove-a-property-from-a-javascript-object ?noredirect=1&lq= 1)
如果删除该属性,其键也会消失:
delete obj.foo
true
Object.keys(obj)
[ 'bar' ]
删除操作仅影响对象的直接(“自身”而非继承)属性。其原型不受影响
- 如果仅将属性设置为未定义,则该属性仍然存在,并且对象仍然包含其键
var obj = { foo: 'a', bar: 'b' };
obj.foo = undefined;
Object.keys(obj)
[ 'foo', 'bar' ]
-
如何在 JavaScript 中解析 JSON?
https://stackoverflow.com/questions/4935632/parse-json-in-javascript ) -
检测未定义的对象属性
https://stackoverflow.com/questions/27509/detecting-an-undefined-object-property?rq=1 ) -
JavaScript 中的对象比较
https://stackoverflow.com/questions/1068834/object-comparison-in-javascript ) -
在 JavaScript 中删除对象
https://stackoverflow.com/questions/742623/deleting-objects-in-javascript ) -
如何获取 JavaScript 对象的大小?
https://stackoverflow.com/questions/1248302/how-to-get-the-size-of-a-javascript-object ) -
对象属性隐藏
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;
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
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
获取所有属性
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"]
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 };
*/
function Rabbit() {}
// by default:
// Rabbit.prototype = { constructor: Rabbit }
alert( Rabbit.prototype.constructor == Rabbit ); // true
...JavaScript 本身并不能确保正确的“构造函数”值。
是的,它存在于函数的默认“原型”中,但仅此而已。之后会发生什么,完全取决于我们。
具体来说,如果我们整体替换默认原型,那么其中就不会有“构造函数”。
例如:
function Rabbit() {}
Rabbit.prototype = {
jumps: true
};
let rabbit = new Rabbit();
alert(rabbit.constructor === Rabbit); // false
因此,为了保留正确的“构造函数”,我们可以选择向默认“原型”添加/删除属性,而不是将其全部覆盖:
function Rabbit() {}
// 不完全覆盖 Rabbit.prototype
// 只需添加到其中
Rabbit.prototype.jumps = true
// 保留默认的 Rabbit.prototype.constructor
或者,手动重新创建构造函数属性:
Rabbit.prototype = {
jumps: true,
constructor: Rabbit
};
// 现在构造函数也是正确的,因为我们添加了它
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] }
数组
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"
-
从 JavaScript 中的对象数组中删除重复项
https://stackoverflow.com/questions/tagged/javascript+arrays ) -
arraylike 与数组
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);
}
字符串的行为也类似于不可变数组,因为它们可以被索引
,并且其长度可以通过 length 属性访问。因此,
Array.prototype 中不修改数组的方法也可以用于
字符串:
var result = Array.prototype.map.call("abc", function(s) {
return s.toUpperCase();
}); // ["A", "B", "C"]
只有一个 Array 方法不是完全泛型的:数组连接方法 concat。此方法可以在任何类似数组的接收器上调用,但它会测试其参数的 [[Class]]。如果参数
是真正的数组,则其内容将连接到结果中;否则,
该参数将作为单个元素添加。这意味着,例如,
我们不能简单地将数组与
参数对象的内容连接起来:
function namesColumn() {
return ["Names"].concat(arguments);
}
namesColumn("Alice", "Bob", "Chris");
// ["Names", { 0: "Alice", 1: "Bob", 2: "Chris" }]
为了让 concat 将一个类数组对象视为真正的
数组,我们必须自己进行转换。一个流行且简洁的
转换方法是调用类数组
对象的 slice 方法:
function namesColumn() {
return ["Names"].concat([].slice.call(arguments));
}
namesColumn("Alice", "Bob", "Chris");
// ["Names", "Alice", "Bob", "Chris"]
https://stackoverflow.com/questions/2218999/remove-duplicates-from-an-array-of-objects-in-javascript
-
如何从 JavaScript 中的数组中删除特定元素?
https://stackoverflow.com/questions/5767325/how-do-i-remove-a-particular-element-from-an-array-in-javascript ) -
如何在 JavaScript 中检查数组是否包含对象?
https://stackoverflow.com/questions/237104/how-do-i-check-if-an-array-includes-an-object-in-javascript ) -
检查对象是否为数组?
https://stackoverflow.com/questions/4775722/check-if-object-is-array ) -
为什么在数组迭代中使用“for...in”是个坏主意?
https://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-a-bad-idea ) -
如何在 Java 中连接两个数组?
https://stackoverflow.com/questions/80476/how-can-i-concatenate-two-arrays-in-java ) -
从 JS 数组中删除重复值
https://stackoverflow.com/questions/9229645/remove-duplicate-values-from-js-array ) -
在 JavaScript 中合并/展平数组数组?
https://stackoverflow.com/questions/10865025/merge-flatten-an-array-of-arrays-in-javascript ) -
**对 JavaScript 对象数组进行 groupby 的最有效方法是什么?
https://stackoverflow.com/questions/14446511/what-is-the-most-efficient-method-to-groupby-on-a-javascript-array-of-objects ) -
**从 JavaScript 中的对象数组中删除重复项
https://stackoverflow.com/questions/2218999/remove-duplicates-from-an-array-of-objects-in-javascript ) -
**从 JS 数组中删除重复值
https://stackoverflow.com/questions/1960473/get-all-unique-values-in-a-javascript-array-remove-duplicates?noredirect=1&lq=1
DOM
-
揭秘原生 DOM API
https://ponyfoo.com/articles/uncovering-the-native-dom-api ) -
DOM 技巧和技术:父级、子级和兄弟级
https://www.sitepoint.com/dom-tips-techniques-parent-child-siblings/ )
问: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
- 现场收藏
所有 getElementsBy* 方法都会返回一个实时集合。此类集合始终反映文档的当前状态,
并在文档发生变化时“自动更新”。
http://javascript.info/searching-elements-dom#live-collections
-
Vanilla JavaScript 中的 DOM 操作基础知识(无 jQuery)
https://www.sitepoint.com/dom-manipulation-vanilla-javascript-no-jquery/ ) -
DOM 事件简介 — Smashing Magazine
https://www.smashingmagazine.com/2013/11/an-introduction-to-dom-events/ )
https://eloquentjavascript.net/15_event.html -
CSS 布局 - 显示属性
https://www.w3schools.com/css/css_display_visibility.asp
https://javascript.info/styles-and-classes -
JavaScript 事件 - w3school
https://www.w3schools.com/js/js_events.asp )
适合快速查看 JavaScript 中的所有事件
https://www.w3schools.com/jsref/obj_event.asp
https://www.w3.org/TR/uievents/#widl-MouseEvent-relatedTarget
-
Event() 构造函数
https://developer.mozilla.org/en-US/docs/Web/API/Event/Event ) -
事件接口
https://developer.mozilla.org/en-US/docs/Web/API/Event )
https://www.w3schools.com/js/js_events.asp)
https://www.w3schools.com/jsref/event_cancelable.asp
- TouchEvent 中的 targetTouches、touches、changedTouches 有什么区别? https://segmentfault.com/q/1010000002870710
https://github.com/krasimir/EventBus
https://stackoverflow.com/questions/2863547/javascript-scroll-event-for-iphone-ipad
-
区分点击与鼠标按下/鼠标弹起
https://stackoverflow.com/questions/12572644/differentiate-click-vs-mousedown-mouseup?noredirect=1&lq=1 -
HTML DOM 事件
https://www.w3schools.com/jsref/dom_obj_event.asp
https://www.w3schools.com/jsref/obj_events.asp
http://javascriptkit.com/javatutors/touchevents.shtml
- 在 JS 中创建自己的长按事件 https://stackoverflow.com/questions/2625210/long-press-in-javascript https://github.com/john-doherty/long-press-event/blob/master/src/long-press-event.js
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);
}
- visibility:hidden 和 display:none 之间有什么区别? https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/hidden https://developer.mozilla.org/en-US/docs/Web/API/Element/closest https://stackoverflow.com/questions/133051/what-is-the-difference-between-visibilityhidden-and-displaynone
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;
}
}
mouseleave 与 mouseover 对比
https://codepen.io/deen_john/pen/jONJwJz?editors=0010
https://www.youtube.com/watch?v=pzT4hAY82q4
- preventDefault https://javascript.info/default-browser-action https://bugzilla.mozilla.org/show_bug.cgi?id=653009 https://stackoverflow.com/questions/30426523/why-does-preventdefault-on-checkbox-click-event-returns-true-for-the-checked-att https://technet.microsoft.com/en-us/windows/ff974940(v=vs.60)
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>
<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>
在上面的例子中,事件顺序为 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.
}
});
上述处理程序会监听文档上的点击事件,并检查事件目标是否
为 #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>
-
在 Android 上长按禁用上下文菜单
https://stackoverflow.com/questions/3413683/disabling-the-context-menu-on-long-taps-on-android?noredirect=1&lq=1 -
clientX vs PageX vs ScreenX
https://heeestorys.tistory.com/778
https://stackoverflow.com/questions/9262741/what-is-the-difference- Between-pagex-y-clientx-y-screenx-y-in-javascript/17705548
https://blog.csdn.net/lzding/article/details/45437707
https://heeestorys.tistory.com/778
https://developer.mozilla.org/en-US/docs/Web/API/Element/clientHeight
https://o7planning.org/en/12293/javascript-mouseevent-tutorial -
事件顺序
事件顺序:
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
-
MOUSEOUT 与 MOUSELEAVE
https://javascript.info/mousemove-mouseover-mouseout-mouseenter-mouseleave
https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_onmouseover_addeventlistener
https://www.w3.org/TR/uievents -
创建自己的visibilitychangeEvent
https://www.html5rocks.com/en/tutorials/pagevisibility/intro/ -
指针事件 IE
https://msdn.microsoft.com/en-us/windows/dn304886(v=vs.71) -
什么是视口?
https://www.kirupa.com/html5/viewport_device_document_size.htm -
DOM 深度解析 -1 -MyNotes
https://github.com/deenjohn/Javascript-revision/tree/master/DOM%20in%20depth%20-1 ) -
innerText 与innerHTML 与textContent
https://www.w3schools.com/jsref/prop_node_textcontent.asp
textContent 获取所有元素的内容,包括和
文章来源:https://dev.to/deen_john/resources-to-master-javascript-3d0p