JavaScript高级程序设计(红宝石书)学习笔记

1.在使用<script>嵌入JS代码时,任何地方都不要出现 "</script>"字符串。

2.使用defer属性可以让脚本在文档完全呈现之后再执行,且按顺序执行。

使用async属性可以表示当前脚本不必等待其他脚本,也不必阻塞文档呈现,不保证安顺序执行

3.函数中省略var定义变量,那这个变量会被定义为全局变量。

let声明的变量不会挂载到window上。

4.对未初始化的变量执行typeof操符回返回undefined值,而对未声明的变量执行typeof操作符同样会返回undefined值。

5.八进制字面值:第一位必须是零(0),然后八进制数字序列,如果字面值的数值超出了范围,那么前导零将被忽略。

let a=070 //56
let b=079 //79

 十六进制字面值的前两位必须是0xI(区分大小写),后跟任何十六进制数字(0~9及A~F),字母大小写均可。

6.对于对象调用Number()函数,先调用对象的valueOf()方法,然后依照前面的规则转换返回的值,如果转换的结果是NaN,则调用对象的toString()方法,然后再次依照前面的规则转换返回的字符串值。

7.parseInt()函数在转换字符串时,更多的是看其时候符合数值模式,他会忽略字符串前面的空格,直至找到第一个非空格字符串,如果第一个字符不是数字或者负号,就会返回NaN。

8.null和undefined没有toString方法,对于null和undefined使用String()方法。

其实String()的本质是调用了toString()方法,只是处理了null和undefined两种特殊情况。

9.switch语句在比较值时使用的是全等操作符,因此不会发生类型转换。

10.函数的参数可以想象为一个局部参数。

function setName(obj){
    obj.name="niko"
    obj=new Object()
    obj.name='s1mple'
}
var person=new Object()
setName(person)
console.log(person) //niko

11.模版字面量也支持定义标签函数,而通过标签函数可以自定义插值欣慰,标签函数会接收被插值极好分割后的模版和每个表达式求值的结果,标签函数本身也是个常规函数,通过前缀到模版字面量来应用自定义行为。

let a =6
let b=9
function simpleTag(string,...expresions){
    console.log(string)
    for(const key of expresions){
        console.log(key)
    }
    return 'sss'
}
let taggedResult=simpleTag`${a}+${b}=${a+b}`
console.log(taggedResult)

//["", "+", "=", ""]
// 6
// 9
// 15
//"sss"

12.使用模版字面量也可以直接获取原始的模版字面量内容(如换行符:\n)而不是呗转换后的字符表示,为此,可以使用默认的String.raw标签函数。

13.Symbol()函数不能与new关键字一起作为构造函数使用,这样做是为了避免创建符号包装对象。 

14.number方法:toPrecision()会风局情况返回最合理的输出结果,可能是固定长度,有可能是科学计数法形式,这个方法接受一个参数,表示结果中数字的总位数(不包含指数)

let num= 99;
console.log(num.toPrecision(1));//'1e+2'   -->对99四舍五入了
console.log(num.toPrecision(2));//‘99’
console.log(num.toPrecision(3));//‘99.0’

15.slice()、substr()、substring(),对于某个参数是负值时的不同处理:

slice:将所有负值参数都当成字符串长度加上负参数值。

substr:降低一个负参数值当成字符串长度加上该值,将第二个负参数值转换成0。

substring:将所有负参数值都转换为0。

let stringValue = "hello world";
console.log(stringValue.slice(-3));        //8 rld
console.log(stringValue.substring(-3));    //0 hello world
console.log(stringValue.substr(-3));       //8 rld
console.log(stringValue.slice(3, -4));     //3-8 lo w
console.log(stringValue.substring(3, -4)); //3-0 hel
console.log(stringValue.substr(3, -4));    //3,0 ''

16.通过eval()定义的任何变量和函数都不会被提升,只是因为在解析代码的时候,他们是被包含在一个字符串中的,他们只是在eval()执行的时候才会被创建。

eval("let msg='ssss';")
console.log(msg) // "Uncaught ReferenceError: msg is not defined"

17.使用instance佛的问题是假定只有一个全局执行上下文,如果网页中有多个框架,则可能涉及两个不同的全局上下文,因此就有两个不同版本的Array构造函数,如果要把数组从一个框架传个另一个框架,则这个数组的构造函数将有别于第二个框架内本地创建的数组。 

18.数组splice()的返回值是被删除的项。 

19.WeakMap的只能是Object或者继承自Object的类型,WeakSet的只能是Object或者继承自Object的类型。

20.Object属性的类型:

        数据属性:数据属性包含一个保存数据值的位置,值会从这个位置读取,也会写入这个位置,数据属性有四个特性描述它们的行为:Configurable,Enumerable,Writable,Value.

        访问器属性:访问器属性不包含数据值,相反,他们包含一个获取函数和一个设置函数,不过这个两个函数不是必须的。访问器属性有四个特性描述它们的行为:Configurable , Enumerable ,Get,Set.

21.使用new操作符:

        在内存中创建一个新对象

        这个对象内部的[[Prototyoe]]特性被赋值为构造函数的prototype属性

        构造函数内部的this被赋值为这个新对象(即this指向新对象)

        执行构造函数内部的代码(给新对象添加属性)

        如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象

22.重写整个原型会切断最初原型与构造函数的关系,丹实例引用的仍然是最初的原型。实例只有指向原型的指针,没有指向构造函数的指针。

function Person(){}
Person.prototypr={
    constructor:Person,
    name:'Niko',
    age:29,
    job:'software Engineer',
    sayHi(){
    console.log('hi')
    }
};
friend.sayHi()//错误

23.函数受函数作用域的限制,而类受块作用域限制

{
function test(){}
class ClassTest(){}
}
console.log(test)// test(){}
console.log(ClassTest)//ReferenceError

24.使用super时的注意点:

        super只能在派生类构造函数和静态方法中使用。

        不能单独引用super关键字,要们用它调用构造函数,要么用它引用静态方法。

        调用super()会调用父类构造函数,并将返回的实例赋值给this

        super的行为如同调用构造函数,如果需要给父类构造函数传参,则需要手动传入

        如果没有定义类构造函数,在实例化派生类时会调用super(),而且会传入所有传入给派生类的参数

        在类构造函数中,不能在调用super()之前引用this

        如果在派生类中显式定义了构造函数,则要么必须在其中调用super,要么必须在其中返回一个对象

25.函数是ECMA中最有意思的部分之一,这主要是因为函数实际上是对象,每个函数都是Function类型的实例,而Function也有属性和方法,跟其他引用类型一样,因为函数是对象,所以函数名就是指向函数对象的指针,而且不一定与函数本身紧密绑定。

26.ES6的所有函数对象都会暴露一个只读的name属性,其中包含关于函数的信息,多数情况下,这个属性中保存的就是一个函数表示符,或者说是一个字符串化的变量名,即使函数没有名称,也会如实显示成空字符串,如果它是使用Function构造函数创造的,则会被表示成‘anonymous'

27.函数如果只传一个参数,然后把arguments[1]设置为某个值,那么这个值并不会反映到第二个命名参数,这是因为arguments对象的长度根据传入的参数个数,而非定义函数时给出的命名函数的个数确定的。

function test(num1,num2){
    console.log(arguments.length)//1
    arguments[1]=10
    console.log(num1,num2,arguments[1])//10,undefined,10
}
test(10)

28.箭头函数没有arguments对象。

29.在使用默认参数时,arguments对象的值不反应参数的默认值,只反映传给函数的参数。

30.js引擎在任何代码执行之前,会先读取函数声明,并在执行上下文中生成函数定义,这个过程叫做函数声明提升;而函数表达式必须等到代码执行到它那一行,才会在执行上下文中生成函数定义。

31.arguments.callee就是一个只想正好在执行的函数的指针

32.闭包外层函数在执行完后,其执行上下文的作用域链会销毁,但它的活动对象仍然会保留在内存中,直到被返回的函数被销毁后才会销毁。

注:活动对象:在函数局部上下文中,包含其中变量的对象,叫做活动对象。

        全局对象:包含全局上下文中的变量的对象叫做全局对象。

33.onRejected处理程序返回的值耶会被Promise.resolve()包装,乍一看可能有点违反直觉,但是想一想,onRejected处理程序的任务不就是捕捉异步错误吗,硬刺拒绝处理程序在捕获错误后不抛出异常是符合期约的行为,应该返回一个解决的契约。

34. 所有超时执行的代码(函数)都会在全局作用于中的一个匿名函数中运行,因此函数中的this值在非严格模式下始终指向window,而在严格模式下是undefined。

持续更新中......

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值