每周一句
低调是为了生活在自己的世界里,高调是为了生活在别人的世界里。
Keeping a low profile is to live in your own world.High profile is to live in other people's world.
——梓哲物语
大家好,一周新姿势又和大家见面了,这是一周新姿势的第2期,希望大家能够多多支持。这一期的干货有点多哦,请自行备好茶水,往下看?
1 forEach
JavaScript诞生已经有20多年了,我们一直使用的用来循环一个数组的方法是这样的:
for (var index = 0; index < myArray.length; index++) {
console.log(myArray[index]);
}
自从JavaScript5起,我们开始可以使用内置的forEach
方法:
myArray.forEach(function (value) {
console.log(value);
});
写法简单了许多,但也有短处:你不能使用break
语句或使用return
语句中断循环。
for-in
JavaScript里还有一种循环方法:for-in
。
for-in循环实际是为循环”enumerable“对象而设计的:
var obj = {a:1, b:2, c:3};
for (var prop in obj) {
console.log("obj." + prop + " = " + obj[prop]);
}
// 输出:
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"
你也可以用它来循环一个数组:
for (var index in myArray) { // 不推荐这样
console.log(myArray[index]);
}
不推荐用for-in来循环一个数组,因为,不像对象,数组的index
跟普通的对象属性不一样,是重要的数值序列指标。
总之,for-in是用来循环带有字符串key的对象的方法。
for of
JavaScript6里引入了一种新的循环方法,它就是for-of循环,它既比传统的for循环简洁,同时弥补了forEach和for-in循环的短板。
我们看一下它的for-of的语法:
for (var value of myArray) {
console.log(value);
}
for-of的语法看起来跟for-in很相似,但它的功能却丰富的多,它能循环很多东西。
Array
) let iterable = [10, 20, 30];
for (let value of iterable) {
console.log(value);
}
// 10
// 20
// 30
我们可以使用const
来替代let
,这样它就变成了在循环里的不可修改的静态变量。
let iterable = [10, 20, 30];
for (const value of iterable) {
console.log(value);
}
// 10
// 20
// 30
let iterable = "boo";
for (let value of iterable) {
console.log(value);
}
// "b"
// "o"
// "o"
TypedArray
) let iterable = new Uint8Array([0x00, 0xff]);
for (let value of iterable) {
console.log(value);
}
// 0
// 255
Map
let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]);
for (let [key, value] of iterable) {
console.log(value);
}
// 1
// 2
// 3
for (let entry of iterable) {
console.log(entry);
}
// [a, 1]
// [b, 2]
// [c, 3]
Set
let iterable = new Set([1, 1, 2, 2, 3, 3]);
for (let value of iterable) {
console.log(value);
}
// 1
// 2
// 3
循环一个DOM collections,比如NodeList
// Note: This will only work in platforms that have
// implemented NodeList.prototype[Symbol.iterator]
let articleParagraphs = document.querySelectorAll("article > p");
for (let paragraph of articleParagraphs) {
paragraph.classList.add("read");
}
for–of循环并不能直接使用在普通的对象上,但如果我们按对象所拥有的属性进行循环,可使用内置的Object.keys()方法:
for (var key of Object.keys(someObject)) {
console.log(key + ": " + someObject[key]);
}
我们可循环一个生成器(generators):
function* fibonacci() { // a generator function
let [prev, curr] = [0, 1];
while (true) {
[prev, curr] = [curr, prev + curr];
yield curr;
}
}
for (let n of fibonacci()) {
console.log(n);
// truncate the sequence at 1000
if (n >= 1000) {
break;
}
}
2 float
属性值:none | left | right | inhert
默认值:none
适用于:所有元素
继承性:无
Values | IE | Firefox | Chrome | Safari | Opera | iOS Safari | Android Browser | Android Chrome |
---|---|---|---|---|---|---|---|---|
Basic Support | 6.0+ | 2.0+ | 4.0+ | 3.1+ | 7.0+ | 3.2+ | 2.1+ | 18.0+ |
实现自适应布局,比如:左侧固定右侧自适应、右侧固定左侧自适应(注意float:right的定义)、左右两侧固定中间自适应、邮箱布局(网易面试题)等。
小提示:可以在本公众号内回复关键词【布局】查看应用场景。
3 pointer-events
属性值:auto | none | visiblepainted | visiblefill | visiblestroke | visible | painted | fill | stroke | all
默认值:auto
适用于:所有元素
继承性:有
visiblepainted
值相同。Values | IE | Firefox | Chrome | Safari | Opera | iOS Safari | Android Browser | Android Chrome |
---|---|---|---|---|---|---|---|---|
Basic Support | 6.0-10.0 | 2.0-3.5 | 4.0+ | 6.0 | 15.0 | 6.0 | 2.1+ | 18.0+ |
11.0+ | 3.6+ |
在你的项目中可能被逼无奈会用到iframe,此时产品大人再给你来个在这个iframe上不允许进行任何操作,这个时候呢,pointer-events这个属性就可以完美的解决你的困惑。
另外,这个属性的兼容性...IE爸爸(不敢惹)和火狐爸爸的较低版本不可以使用,你可以通过下面一段代码来检测你的浏览器的pointer-events属性是否可用。
let supportsPointerEvents = (function(){ let dummy = document.createElement('_'); if(!('pointerEvents' in dummy.style)) return false; dummy.style.pointerEvents = 'auto'; dummy.style.pointerEvents = 'x'; document.body.appendChild(dummy); let r=getComputedStyle(dummy).pointerEvents==='auto'; document.body.removeChild(dummy); return r;})();
4 hasOwnProperty()和in的区别
in判断的是对象的所有属性,包括对象实例及其原型的属性; 而hasOwnProperty则是判断对象实例的是否具有某个属性。
示例代码
<script type="text/javascript">
function Person(){}
Person.prototype.name = "allen";
let person = new Person();
console.log(person.hasOwnProperty("name")); //false
console.log("name" in person); //true
console.log(person.name); //"allen"
person.name = "justforse";
console.log(person.hasOwnProperty("name")); //true
console.log("name" in person); //true
console.log(person.name); //"justforuse"
delete person.name;
console.log(person.hasOwnProperty("name")); //false
console.log("name" in person); //true
console.log(person.name); //"allen"
</script>
以上代码执行的时候,name属性要么是从实例中获取的,要么是来源于原型,所以使用in 来访问 name属性始终返回true;而hasOwnProperty()只在属性存在与对象实例中时才返回true,当删除了实例中的name属性后,就恢复了原型中name属性的连接,所以返回allen。
__proto__和prototype的区别
__proto__是什么? __proto__是JavaScript中对象实例所拥有的一个属性,它指向的是该对象实例所对应的prototype对象。(需要注意的是,如上所述,Object.prototype是所有对象继承的顶点,而它的__proto__的值为null。另外__proto__ 并不是语言本身的特性,这是各大厂商具体实现时添加的私有属性,虽然目前很多现代浏览器的 JS 引擎中都提供了这个私有属性,但依旧不建议在生产中使用该属性,避免对环境产生依赖。生产环境中,我们可以使用 Object.getPrototypeOf 方法来获取实例对象的原型,然后再来为原型添加方法/属性。 )
__proto__与prototype的区别则在于,__proto__是对象固有的属性,它指向的是该对象实例的构造函数的prototype(Object.prototype除外),而prototype是函数固有的属性,其值是一个函数的原型对象。
示例代码
function Test() {}
let t = new Test();
console.log(t.__proto__ === Test.prototype) //true
console.log(t.prototype) //undefined
此处,Test是一个函数,而t是通过Test构造出的Test的实例,t.__proto__指向的是Test.prototype,而t本身是没有prototype这个属性的。
总结: 1、__proto__是对象固有的属性,它指向的是该对象实例的构造函数的prototype(Object.prototype除外)。 2、prototype是函数固有的属性,其值是一个函数的原型对象。 3、__proto__与prototype的联系在于:当一个对象要查找自己没有的属性或者方法时,它是通过__proto__属性去查找,而不是通过prototype属性,对象实例本身是没有prototype属性的。
温馨提示
这一周的新姿势又要告一段落了,喜欢的朋友可以关注一下,分享一下,咱们下周见啦~
上一期:
《一周“新姿势”》