-
一些优雅的写法
逻辑运算符if (a == 1) { b() } // 可以写成 a == 1 && b() if (conected) { login(); } // 可以写成 conected && login(); // 如果一些属性或函数存在于一个对象中,你也可以这样做检测,如下面的代码所示: user && user.login();
初始化变量
var a = obj || {} var name = name || "Oliver Queen";
-
类型转换
("""" + ) > String() > .toString() > new String()
多字符串拼接,先压数组,后
join
尽量使用直接量,区别在于引擎直接解释和调用具体数据类型内部构造器。
字符串操作尽量不用循环,而使用正则表达式,区别在于JavaScript引擎运行逻辑与调用C语言API。
同理,三元比较返回大小与
Math.min
相比,应选择后者。自定义高级对象和
Date
、RegExp
对象在构造时都会消耗大量时间。如果可以复用,应采用缓存的方式。JavaScript中各种高度、宽度:辨析详解:
Name | Code |
---|---|
网页可见区域宽 | document.body.clientWidth |
网页可见区域宽 | document.body.clientWidth |
网页可见区域高 | document.body.clientHeight |
网页可见区域宽 (包括边线的宽) | document.body.offsetWidth |
网页可见区域高 (包括边线的宽) | document.body.offsetHeight |
网页正文全文宽 | document.body.scrollWidth |
网页正文全文高 | document.body.scrollHeight |
网页被卷去的高 | document.body.scrollTop |
网页被卷去的左 | document.body.scrollLeft |
网页正文部分上 | window.screenTop |
网页正文部分左 | window.screenLeft |
屏幕分辨率的高 | window.screen.height |
屏幕分辨率的宽 | window.screen.width |
屏幕可用工作区高度 | window.screen.availHeight |
屏幕可用工作区宽度 | window.screen.availWidth |
!!variable
做检测,只要变量的值为:false
、0
、null
、" "
、undefined
或者NaN
都将返回的是false
,反之返回的是true
。使用
+variable
将String
和Date
直接转为数字。-
数组原生函数方式获取元素:
var array = [1,2,3,4,5,6]; console.log(array.slice(1,2)); // [1,2] console.log(array.slice(3)); // [3,4,5,6] console.log(array.slice(-1)); // [6] console.log(array.slice(-2)); // [5,6] console.log(array.slice(-3)); // [4,5,6]
数组截断可以直接指定数组
length
属性等于想要的长度即可。-
字符串替换所有:
var string = "john john"; console.log(string.replace(/hn/, "ana")); // "joana john" console.log(string.replace(/hn/g, "ana")); // "joana joana"
-
合并数组:
var array1 = [1,2,3]; var array2 = [4,5,6]; console.log(array1.push.apply(array1, array2)); // [1,2,3,4,5,6]; 原理是拼起来。 console.log(array1.concat(array2)); // [1,2,3,4,5,6]; 原理是生成一个新的数组。
-
NodeList to Array
var elements = document.querySelectorAll("p"); // NodeList var arrayElements = [].slice.call(elements); // Now the NodeList is an array var arrayElements = Array.from(elements); // This is another way of converting NodeList to Array
-
数组元素的洗牌
var list = [1,2,3]; console.log(list.sort(() => Math.random() - 0.5)); // [2,1,3]
-
JavaScript获取对象的属性的三种方法
for...in: 该方法依次访问一个对象及其原型链中所有可枚举的属性 Object.keys(O): 该方法返回一个数组,它包含了对象O自身的所有可枚举属性的名称 Object.getOwnPropertyNames(O):该方法返回一个数组,它包含了对象O所有拥有的属性(包括不可枚举)的名称
-
JavaScript中substring()、substr()、slice()的区别
var stringValue = "hello world";
Code | Comments |
---|---|
stringValue.slice(3) |
"lo world" |
stringValue.substring(3) |
"lo world" |
stringValue.substr(3) |
"lo world" |
stringValue.slice(3,7) |
"lo w" |
stringValue.substring(3,7) |
"lo w" |
stringValue.substr(3,7) |
"lo worl" |
stringValue.slice(-3) |
"rld" 从后往前数3个开始 |
stringValue.substring(-3) |
"hello world" 为负,默认从0开始 |
stringValue.substr(-3) |
"rld" |
stringValue.slice(3,-4) |
"lo w" 下标从3开始到-4(从后往前数4个) |
stringValue.substring(3,-4) |
"hel" |
stringValue.substr(3,-4) |
"" 长度为负,默认不显示 |
-
~~
运算符用在JavaScript中有按位取反的作用,~即是取反两次,而位运算的操作值要求是整数,其结果也是整数,所以经过位运算的都会自动变成整数,可以巧妙的去掉小数部分,类似于parseInt
,比如:let a = 1.23; let b = -1.23; console.log(~~a); // 1 console.log(~~b); // -1
-
||
运算符
巧妙的使用||
运算符我们可以给变量设置默认值,比如:let c = 1; let d = c || 2; // 如果c的值为true则取存在的值,否则为2 console.log(d); // 1
-
...运算符
...运算符是ES6中用于解构数组的方法,可以用于快速获取数组的参数,比如:let [num1, ...nums] = [1, 2, 3]; console.log(num1); // 1 console.log(nums); // [2, 3]
-
new Set()
可能有人知道ES6中提供了新的数据结构 Set,但是能够灵活运用的人或许不多。利用Set数据结构我们能够轻松的去重一个数组,比如:let arr = [1, 2, 2, 3]; let set = new Set(arr); let newArr = Array.from(set); // Array.from方法可以将 Set 结构转为数组。 console.log(newArr); // [1, 2, 3]
-
Object.assign()
Object.assign()也是ES6中提供的对象的扩展方法,其可以用于对象的合并拷贝,比如:let obj1 = {a: 1}; let obj2 = {b: 2}; let obj3 = Object.assign({}, obj1, obj2); console.log(obj3); // {a: 1, b: 2}
-
注入
evilCode.replace(/.+/,eval)//
-
JavaScript中访问属性和访问变量的标识符查找规则
标识符查找- 访问属性,查找的是原型链;
- 访问变量,查找的是作用域链;
当通过属性调用的方式调用对象的方法时,该对象只会成this的值;不会成为它的方法(即:对象中属性值是函数的属性)的作用域链中的作用域对象,不过可以通过with操作符使对象成为它的方法的作用域链中的作用域对象。
gby; //结果:报错:ReferenceError: Can't find variable: gby; window.gby; //结果:undefined
访问变量时是通过搜索作用域链来查找变量的,而访问属性是通过搜索原型链来查找属性的,因为这两种访问方式的搜索方式不一样,所以导致了结果不一样;
-
以下来自内容部分来自《浅谈JavaScript、ES5、ES6》:
-
ES6支持动态声明对象属性
const obj = { [ 'prop_' + (() => 42)() ]: 42 } console.log(obj); // {prop_42: 42}
-
赋值解构
let singer = { first: "Bob", last: "Dylan" }; let { first: f, last: l } = singer; // 相当于 f = "Bob", l = "Dylan" let [all, year, month, day] = /^(dddd)-(dd)-(dd)$/.exec("2015-10-25"); // v8 不支持? let [x, y] = [1, 2, 3]; // x = 1, y = 2 let [, , x, y] = [1, 2, 3]; // x = 3, y = undefined
-
函数参数 - 默认值、参数打包、 数组展开(Default 、Rest 、Spread)
// Default function findArtist(name = 'lu', age = '26') { console.log(name, age); } findArtist(...['li', ]); // li 26 // Rest function f(x, ...y) { // y is an Array return x * y.length; } console.log(f(3, "hello", true)); // 6 // Spread function f2(x, y, z) { return x + y + z; } // Pass each elem of array as argument console.log(f2(...[1, 2, 3])) // 6
Iterators(迭代器)+
for..of
。迭代器有个next
方法,调用会:
(1).返回迭代对象的一个元素:{ done: false, value: elem }
(2).如果已到迭代对象的末端:{ done: true, value: retVal }-
Class
class Artist { constructor(name) { this.name = name; } perform() { return this.name + " performs "; } } class Singer extends Artist { constructor(name, song) { super(name); this.song = song; } perform() { return super.perform() + "[" + this.song + "]"; } } let james = new Singer("Etta James", "At last"); console.log(james instanceof Artist); // true console.log(james instanceof Singer); // true console.log(james.perform()); // "Etta James performs [At last]"
-
Modules
ES6的内置模块功能借鉴了CommonJS和AMD各自的优点:
(1).具有CommonJS的精简语法、唯一导出出口(single exports)和循环依赖(cyclic dependencies)的特点。
(2).类似AMD,支持异步加载和可配置的模块加载// lib/math.js export function sum(x, y) { return x + y; } export var pi = 3.141593; // app.js import * as math from "lib/math"; alert("2π = " + math.sum(math.pi, math.pi)); // otherApp.js import { sum, pi } from "lib/math"; alert("2π = " + sum(pi, pi)); // Dynamic loading – ‘System’ is default loader // Module Loaders: System.import('lib/math').then(function (m) { alert("2π = " + m.sum(m.pi, m.pi)); }); // Directly manipulate module cache System.get('jquery'); System.set('jquery', Module({ $: $ })); // WARNING: not yet finalized
-
Map + Set + WeakMap + WeakSet
四种集合类型,WeakMap、WeakSet作为属性键的对象如果没有别的变量在引用它们,则会被回收释放掉。// Sets var s = new Set(); s.add("hello").add("goodbye").add("hello"); s.size === 2; s.has("hello") === true; // Maps var m = new Map(); m.set("hello", 42); m.set(s, 34); m.get(s) == 34; //WeakMap var wm = new WeakMap(); wm.set(s, { extra: 42 }); wm.size === undefined // Weak Sets var ws = new WeakSet(); ws.add({ data: 42 }); //Because the added object has no other references, it will not be held in the set
-
Math + Number + String + Array + Object APIs 一些新的API
Number.EPSILON Number.isInteger(Infinity) // false Number.isNaN("NaN") // false Math.acosh(3) // 1.762747174039086 Math.hypot(3, 4) // 5 Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2 "abcde".includes("cd") // true "abc".repeat(3) // "abcabcabc" Array.from(document.querySelectorAll('*')) // Returns a real Array Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior [0, 0, 0].fill(7, 1) // [0,7,7] [1, 2, 3].find(x => x == 3) // 3 [1, 2, 3].findIndex(x => x == 2) // 1 [1, 2, 3, 4, 5].copyWithin(3, 0) // [1, 2, 3, 1, 2] ["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"] ["a", "b", "c"].keys() // iterator 0, 1, 2 ["a", "b", "c"].values() // iterator "a", "b", "c" Object.assign(Point, { origin: new Point(0, 0) }) plain
-
Proxies 使用代理(Proxy)监听对象的操作,然后可以做一些相应事情。
可监听的操作:get
、set
、has
、deleteProperty
、apply
、construct
、getOwnPropertyDescriptor
、defineProperty
、getPrototypeOf
、setPrototypeOf
、enumerate
、ownKeys
、preventExtensions
、isExtensible
。var target = {}; var handler = { get: function (receiver, name) { return `Hello, ${name}!`; } }; var p = new Proxy(target, handler); p.world === 'Hello, world!'; // true
-
Symbol是一种基本类型。Symbol 通过调用symbol函数产生,它接收一个可选的名字参数,该函数返回的symbol是唯一的。
var key = Symbol("key"); var key2 = Symbol("key"); key == key2 // false
-
Promises是处理异步操作的对象,使用了 Promise 对象之后可以用一种链式调用的方式来组织代码,让代码更加直观。
function fakeAjax(url) { return new Promise(function (resolve, reject) { // setTimeouts are for effect, typically we would handle XHR if (!url) { return setTimeout(reject, 1000); } return setTimeout(resolve, 1000); }); } // no url, promise rejected fakeAjax().then(function () { console.log('success'); }, function () { console.log('fail'); });
替换字符串最后一个匹配,参考
str.replace(/(.*)and/, '$1but');// 正则表达时,贪婪模式,.*会一直匹配到最后一个
-