《JavaScript高级程序设计》第二次阅读笔记

第二章

  1. <!CDATA[   javascriptCode  ]]>   在XHTML中javascript可以用这个标记保证内嵌的javascript代码能正常运行,因为XHTML标准比较严格,很多标签都不能被解析。

  2. defer和async标记都不能保证是在DOMContentLoading之前或之后执行,区别就只是保证顺序执行而已。

第三章

  1. 严格模式下,使用未定义的变量会导致错误。

  2. nul值表示一个空对象的指针,而这也是使用typeof操作符检测null值时返回“object”的原因

  3. 无论在什么情况下都没必要把一个变量的值显式地设置为undefined,但是对于null,只要在保存[对象]的变了还没有真正保存对象,就应该明确地然它保存为null值。

  4. undefined 和 null,没有任何属性和方法

   5.要把都一个值转换为字符串,可以用加号把它与一个字符串“xxx”加在一起

   6.并非所有浏览器的BOM与DOM都属于Object

   7.+操作符 会像Number()一样对这个值执行转换。-号同理,不过变成负数。

   8.do-while 循环的代码至少会执行一次。

   9.for(; ;){ doSomething(); } 无限循环

   10.通过for-in循环输出的属性名的顺序是不可预测的,具体先后顺序因浏览器而异。

   11.swicth{case xxx:} 在比较时是使用全等操作符 ===,所以10不等于“10”

   12. 标准模式下arguments与参数会相互同步,严格模式下不会同步。

标准模式下:
function add(a){
arguments[0] = 10;
console.log(a); //10
}
add(1);
严格模式下
function add(a){
        "use strict";
arguments[0] = 10;
console.log(a);//1
}
add(1);

第4章

  1. 给基本类型添加引用会被浏览器直接忽略,也不会报错。

   2.要检测一个变量是不是基本数据类型用typeof,typeof null 等于object。如果用instanceof操作符检测基本类型的值,则翻回false.

第5章

   1.对象的key只能用字符串作key

   2.数组的toString()方法会返回由数组中每一个值的字符串形式拼接逗号分隔而成的字符串。所以如果[{a:1},2] toString() 等于 [object Object],2

   3.concat()方法可以添加字符串,也可以添加数组。如:

    var colors = ["red","green","blue"];

    var colors2 = colors.concat("yellow",["black","brown"]);

    alert(colors);//red,green,blue

    alert(color2);//red,green,blue,yellow,black,brown

   4.Array的5个迭代方法,都是给定运行参数function(value,index,array){}

    1.every() //返回布尔值,每一项都是true的话,返回true

    2.filter() //将返回true的项组成新的素组

    3.forEach()//仅仅循环数组一次.没有返回值

    4.map()//将每一项的返回值组成新的数组

    5.some()//返回布尔值,其中一项返回true,则返回true

   5.关于函数是否能复制,目前只能想到eval 这种方法了 eval("var z = "+s1.toString());

   6.创建函数有一种新的思路

      var sum = function(num1, num2){

              return num1 + num2;

      }

    等于

继续阅读

关于instanceof的深入认识

如果刚认识这个操作符,有个肤浅的理解

a instanceof b 只要在a的原型链上有b就返回true。这个理解其实是错的。

直到我重新读了一下《javascript高级程序设计》的6.3节 173页。

function inheritPrototype(subType, superType){
	var prototype = Object(superType.prototype);
	prototype.constructor = subType;
	subType.prototype = prototype;
}
function SuperType(name){
	this.name = name;
	this.colors  = ["red","blue","green"];
}
SuperType.prototype.sayName = function(){
	alert(this.name);
}
function SubType(name,age){
	SuperType.call(this, name);
	this.age = age;
}
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge = function(){
	alert(this.age);
}
var instance = new SubType("jie",29)

instance instanceof SubType //true 这个没有异议吧

instance instanceof SuperType //true 这个就比较奇怪了

如果console.log(instance);是看不到SuperType出现在instance的原型链上面的。

于是我上百度谷歌了一下:

a instanceof b底层的运算机制关键点如下:

1 b的数据类型必须为[object Function],否则就抛TypeError;

2 若a为Primitive Value则直接返回false, 若a的数据类型为Object则执行后续运算;

3 当且仅当b.prototype位于a的prototype chain中时,才返回true(由于Object.prototype.__proto__为null,因此prototype chain是有限链表);

所以正确的说法是   a instanceof b 只要在a的原型链上有等于b的原型就返回true

对象属性的理解

var person = {name:"jie",age:18};
如果只是这样定义一个object,那么configurable:true,Enumerable:true,writable:true;
要改变这些属性类型,需要显式的调用Object.defineProperty
Object.defineProperty(person,"name",{
    configurable:false, //能否被删除,能否修改访问属性,默认true,如果在false重设defineProperty会报错
    Enumerable:false,//能否被for-in,默认为true
    writable:false, //能否修改,默认为true
    value:"gax"
})
console.log(person); //{name: "gax",age:18}
person.name = "abc";
console.log(person); //{name: "gax",age:18}
[configurable]
Object.defineProperty(person,"name",{
    configurable:false,
	value:"jie"
})
delete person.name; //报错
Object.defineProperty(person,"name",{
    value:"jie2"
})//报错
configurable如果被设置false,那么如果delete会报错,
如果configurable,Enumerable,writable,value中,任意一项于初始值不一致,都会报错
[Enumerable]
var person = {name:"jie"};
Object.defineProperty(person,"age",{
    Enumerable:false,
	value:"18"
})
for(var x in person){
	console.log(x);
}
//只有name
[writable]
var person = {};
Object.defineProperty(person,"age",{
    writable:false,
    value:"18"
})
person.age = 21;//依然是 18
如果
var person = {};
Object.defineProperty(person,"age",{
    value:"18"
})
那么Object.getOwnPropertyDescriptor(person,"age")//{value: 18, writable: false, enumerable: false, configurable: false}
全部未定义的默认全部false
同理适用于new出来的实例:
function person(){
	Object.defineProperty(this,"age",{
		writable:false,
		value:"18"
	})
}
var son = new person();
这样就能做到对象中的权限控制。

当变量提升遇到作用块

function aaa(){
    a();
    if(true){
        function a(){
            console.log(1);
        }
    }
    if(false){
        function b(){
            console.log(2)
        }
    }
    function a(){
        console.log(3);
    }
}
与
function aaa(){
    a();
    function a(){
        console.log(3);
    }
    if(true){
        function a(){
            console.log(1);
        }
    }
    if(false){
        function b(){
            console.log(2)
        }
    }
}
结果都是3,证明fuction的变量提升是只在当前作用块内。

关于图片阻塞的探索

我现在正在给m.360zfw.com做首屏速度优化,对于图片阻塞这一块,有以下问题

问题1:img上的图片阻塞是否会影响首次页面渲染

demo

现象:div.a div.b 同时出现,3秒后出现头像

结论:说明img不会阻塞首屏渲染。

问题2:那么background-images上的图片呢?

demo

想象结论同上。

关于JS页面阻塞的实验

问题1:如果遇到JS阻塞,那么它的阻塞是指阻塞DOM建立,还是阻塞显示(渲染),如果是阻塞DOM建立,那么是全部DOM都阻塞还是部分阻塞?

[DEMO]

现象:先出现红色,3秒后出现蓝色。

结论:说明JS只是阻塞JS脚本下面的DOM。

问题2:如果这个JS阻塞不是因为外链下载消耗的阻塞,而是<script>内部js的计算运行造成的阻塞,那么<script>上面的DOM会被渲染吗?

[DEMO]

现象:红色蓝色一起出现。

结论:说明JS脚本的阻塞如果是[网络原因],就会部分阻塞,如果是[运行原因],就会全部阻塞。