你不知道的JavaScript上卷笔记

豆瓣评分:9.4

GitHub开源书籍

JavaScript进阶必读书籍

第一部分作用域和闭包

第一章:作用域是什么

JavaScript有一个预编译的过程,

两个知识点:LSH、RHS查询。

LHS左查询,找到变量,如果没有找到,会在全局热心创建一个,如果是严格模式,就报错。(赋值符号的左边就是LHS查询)

RHS右查询, 取得变量的值,如果没有找到会报错referenceError。(获取变量的值,或者执行函数就是RHS查询)

作用域: 存储变量找到变量的规则。

第二章:词法作用域

欺骗语法:

动态生成代码:动态生成代码并不推荐使用

1、因为它带来的好处无法吊销性能上的损失。

2、eval还会受严格模式影响。

两个语法:

eval(“var b = 10”) 根据传入的字符串动态变量。

with(“对象参数”){}

第三章:函数作用域与块作用域

区分函数声明和表达式

function是第一个词语就是函数声明,否则是表达式。

区别:

  1. 函数声明会被提升到当前作用域的顶部
  2. 函数声明需要命名,而函数表达式可以选择命名或者使用匿名函数

一个技巧:

使用函数表达式时,应当给函数命名,报错的时候,容易快速找到位置。

第四章:提升

编译阶段的一部分工作就是找到所有的声明,并用合适的作用域将他们关联起来。

var变量和函数声明会提升

var fn = function demo(){} demo并部会提升

第五章:作用域闭包

能够访问其他函数作用域中的变量的函数就是闭包函数

当一个函数可以记住并访问它所在的词法作用域时,就产生了闭包。简单来说,闭包就是指有权访问另一个函数作用域中变量的函数。

This和原型对象

两个误区:

  1. 指向函数自身。

如果函数内部要引用自己,可以用自己的函数名来引用,匿名函数通过arguments也可以找到自己。也可以在函数调佣的时候 fn.call(fn,.....)

  1. This指向函数的作用域。

函数在任意时候都不指向自己的词法作用域。

this既不指向函数自身也不指向他的词法作用域(默认情况)

this到底是什么? this是在运行时绑定的,并不是在编写时绑定的,它取决于函数调用的各种条件,与函数声明的位置没有任何关系,取决于函数调用方式

this是运行时绑定的,它取决于函数调用时的各种条件

默认绑定,直接调用 this就是windows

隐式绑定, 通过对象调用,this就是对象

显示绑定 call、apply、bind

New 绑定。

函数的this优先级:

如果函数是new 调用,this指向实例对象

如果是通过call/apply/bind进行绑定,this指向他们的第一个参数

如果函数是通过某个对象调用,this指向这个对象

如果都是,严格模式this是undefined ,非严格模式windows

箭头函数永不修改this,默认指向在定义它时所处的对象(宿主对象),此处指父级作用域

第三章对象

1、null被当做”object” 其实是语言本身的bug。

原因对象在底层标识为二进制,在JavaScript中二进制前三位0的话会判断为object类型null的二进制表示是全0.所以typeof 时会返回object。

2、内容,对象中的属性也称之为内容, 对象的属性名永远是字符串。可以通过obj.key 或者obj[key] 访问,不同是obj.key需要符合标识符命名规范,[key]可以是任意Utf-8的字符串。

  1. 注意:属性名永远是字符串,使用其他类型做属性,会先转为字符串
  2. 数组也是对象,存储 数值/值对 可以像对象一样给数组添加属性,不影响数组的长度,不过他的键是一个数字 或者 能看起来像一个 数字 “3”,(整数)那么它就会修改数组的内容。函数是可调用的对象,可以给函数添加属性例如fn.msg= ‘函数fn’
  3. For in 和 会检查原型链
  4. obj.hasOwnProperty("key") 只会检查自己本身
  5. Object.create 可以理解为创建一个对象,并把这个对象的prototyep指向复制 的对象

第四章原型

JavaScript对象都有一个特殊的【prototype】的内置属性,指向他的原型对象,原型链的顶端是Object.prototype。

Prototype机制就是对象中一个内部的连接引用另一个对象

什么是原型链

Js中对象都有一个特殊的内置属性【prototype】,指向它的原型对象,访问一个对象中不存在的属性时,就会沿着这条prototype链查找。

属性设置和屏蔽:

给对象的属性设置值时会有三种情况:

  1. 如果原型上有这个属性并且设置了setter,那它一定会调用这个setter
  2. 默认情况下是给对象添加或者修改这个属性的值
  3. 严格模式的话,如果对象身上没有这个属性,会报错。严格模式阻止了对未定义属性进行隐式创建的行为,以提供更严格的错误检查。

属性屏蔽是什么?

一个对象的新属性名称与其原型链上的属性名称相同,从而屏蔽了原型链上属性的访问或修改。

// 定义一个父对象

var parent = {

    x: 10

};

// 创建一个子对象,它的原型指向 parent

var child = Object.create(parent);

child.x++

// child.x = child.x + 1 给子对象添加一个x属性,从而屏蔽掉了parent的x的访问

类函数(构造函数):

构造函数就是new调用的函数,JavaScript中是没有类的,然后衍生出一种滥用的模仿类,通常使用构造函数来模仿类。

执行new的步骤

1、创建一个空对象{}

2、将空对象的【prototype】属性指向 构造函数.prototype

3、执行函数体,并将this绑定到对象上

4、如果函数返回对象或者数组类型,则返回改值。否则返回创建的对象

错误观点和方式:

  1. let fn = new Fn() fn是由Fn构造的
  2. Bar.prototype =  Fn.prototype 实现集成,实际上没有关联,是地址引用
  3. Bar.prototyp = new Fn() 建议使用Objeact.create()

关联关系:

instanceof左边是一个普通的对象,右边是一个函数。

Instanceof 回答的是在 对象的整条【prototype】链上,是否有 右边函数的.prototype指向的对象

知识点:
1、Object.create

语法:

let ojb = Object.create(要关联的对象, {

  // 可选参数 配置其他属性

c: {

   

        value: 'c'

    }

})

创建一个对象,并把对象的【prototype】指向 要关联的对象

ES5之前可以使用

if(!Object.create){

    Object.create = function(o){

        function F(){}

        F.prototype = o

        return new F()

    }

}

2、obj.hasOwnProperty(key)

判断obj身上有没有某个属性,(不会沿着原型链查找)

3、获取对象原型

Object.getPrototypeOf(obj) 获取对象的“原型对象”

还有一种方法__proto__ 在es6之前并不是官方的,但是也有大多数浏览器支持

  1. .constructor

对象的.constructor默认指向一个函数,而这个函数也叫做prototype的引用指向的对象,constructor并不标识对象被它构造,JavaScript的继承需要手动修改prototype.constructor的指向。【结论:.constructor并不可靠】

第一种情况:

    function Fn(){

         this.name = "666"

    }

    Fn.prototype = {

        name:'测试'

    }

    var a = new Fn();

    console.log(Fn.prototype.constructor ) // ƒ Object()

    console.log(a.constructor == Fn) // false 应该是 == Objeact

第二种情况

    function Fn(){

        this.name = "666"

}

// 如果prototype != 赋值给一个对象也可以不用指向

    Fn.prototype.constructor = Fn 

    var a = new Fn();

    console.log(Fn.prototype.constructor == Fn) // true

    console.log(a.constructor == Fn) // true

  1. JavaScript中的继承方式

Parent.prototype.makeMoney = function () {

  console.log(this.name,'定个小目标,赚了一个亿!')

}

// 父类的构造函数

function Parent() {

  this.colors = ['red', 'blue'];

}

// 子类的构造函数

function Child() {

Parent.call(this,...)

}

// 这种方式有两个坏处

// 1、会执行代码体

// 2、不够直观

Child.prototype = new Parent()

// Child.prototype = Object.create(Parent) 推荐使用

Child.prototype.constructor =  Child

var c1 = new Child()

c1.colors.push("black")

var c2 = new Child()

6、ES6修改对象的【prototype】

Bar.prototype = Object.create(Fn.prototype);

let bar = new Bar()

bar.constructor.name // Object

ES6标准可靠的方式修改对象的prototype关联

Object.setPrototypeOf(Bar.prototype, Fn.prototype);

let bar = new Bar()

bar.constructor.name  // Bar

7、判断对线的关联关系

instanceof左边一个对象,右边一个函数。怎么来判断两个对象的关联关系

两种方法,判断对象a是否在b的原型上

let Fn = function (){}

Fn.prototype = 对象a

console.log(对象b instanceof Fn)

console.log(对象a.isPrototypeOf(对象b))

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值