JavaScript 高级

第一天

JS的组成

  • Ecmascript

    描述了该语言的语法和基本对象

  • DOM

    描述了处理网页内容的方法和接口

  • BOM

    描述了与浏览器进行交互的方法和接口

创建对象的三个方法

字面量的方式

  1. let per1 = {
  2. name: '卡卡西',
  3. age: 20,
  4. sex: '男',
  5. eat: function () {
  6. console.log("吃臭豆腐")
  7. },
  8. readBook: function () {
  9. console.log("琴儿天堂")
  10. }
  11. }

调用系统的构造函数

  1. let per2 = new Object()
  2. per2.name = "大蛇丸"
  3. per2.age = 30
  4. ......

自定义构造函数

  1. function Person (name, age, sex) {
  2. this.name = name
  3. this.age = age
  4. this.sex = sex
  5. this.play = function () {
  6. console.log("天天打游戏")
  7. }
  8. // 因为new 这个关键字 进行了函数的构造调用
  9. var per = new Person('周田', 18, '女')
  10. /*
  11. 1、开辟空间存储对象
  12. 2、把this设置为当前“通过new创建对象后返回的对象”
  13. 3、设置属性和方法的值
  14. 4、把this对象返回
  15. **/
  16. }

工厂模式

  1. function createObjectFn (name, age) {
  2. let obj = new Object()
  3. obj.name = name
  4. obj.age = age
  5. obj.sayHi = function () {
  6. console.log('你好')
  7. }
  8. return obj
  9. }
  10. let per1 = createObjectFn('赵思', 22)

构造函数和实列对象之间的关系

  1. function Person (name, age, sex) {
  2. this.name = name
  3. this.age = age
  4. this.sex = sex
  5. this.play = function () {
  6. console.log("天天打游戏")
  7. }
  8. }
  9. let per1 = new Person('小苏', 38, '女')
  10. consoloe.log(per.constructor === Person) //true
  11. consoloe.log(per.__proto__.constructor === Person) // true
  12. Person.protype.constructor === Person // true
  • 实例对象时通过构造函数来创建的
  • 实例对象的构造器指向其构造函数
    1565885052858.png

通过原型对一个构造函数创建出来的对象进行数据共享

  1. function Person(name, age) {
  2. this.name = name
  3. this.age = age
  4. }
  5. Person.prototype.eat = function () {
  6. console.log('在构造函数原型上的方法,其创建出来的对象共享')
  7. }
  8. let p1 = new Person('hjj', 20)
  9. let p2 = new Pserson('jjj', 30)
  10. console.log(p1.eat === p2.eat) // true

构造函数中的this指向问题

  1. function Person(name, age) {
  2. this.name = name
  3. this.age = age
  4. }
  5. Pserson.prototype.init = function () {
  6. // 此this是实列对象
  7. // 打印出来的this没有prototype 只有_proto_ 不是构造函数
  8. console.log(this)
  9. }
  10. let p1 = new Pserson('dwd', 20)
  11. p1.init()

原型对象中的方法是可以相互调用的

1566132503767.png

1566132528152.png

原型链中的属性查找规则

1566132818066.png

  1. <script>
  2. function Person(age, sex) {
  3. this,age=age;
  4. this sex=sex:
  5. this eat= function () {
  6. conso1e.1og("构造函数中的吃")
  7. }
  8. };
  9. person. prototype. sex="女";
  10. var per=new Person(20, "51");
  11. console.log (per sex); //1
  12. console.dir(per); // 打印出来的性别是男 说明 先从实列对象中查找属性
  13. </script>

稍微总结

构造函数可以实例化一个对象

构造函数中有一个属性prototype这是构造函数的原型对象

prototype对象中有一个属性是constructor构造器,这个构造器指向的就是自己所在的原型对象所在的构造函数

构造函数实列化出来的实列对象的属性__proto__(非标准属性,浏览器使用)指向的是该构造函数的原型对象

第二天

函数也是对象

  1. function Person (age) {
  2. this.age = age
  3. }
  4. // 函数也可以通过.的方式 可以说明其也是对象
  5. Person.prototype.sayHi = function () {
  6. }

第三天

实例对象和原型对象之间的关系是通过proto原型来联系起来的,这个关系,就是原型链

原型的指向是否可以改变

通过改变原型链来实现继承

改变原型对象的时候直接初始化了属性 ,继承过来的属性都是一样的

可以通过后续obj.name = xxx 来改变属性

  1. function Person(name, age, sex) {
  2. this.name = name
  3. this.sex = sex
  4. this.age = age
  5. }
  6. Person.prototype.eat = function () {
  7. console.log('人可以吃东西')
  8. }
  9. Person.protype.sleep = function () {
  10. console.log('睡觉')
  11. }
  12. Person.prototype.play = function () {
  13. console.log('玩玩')
  14. }
  15. // 学生构造函数
  16. function Student(score) {
  17. this.score = score
  18. }
  19. // 改变学生原型的指向
  20. /*
  21. 缺陷在于:
  22. 1.改变原型指向的同时实现继承,直接初始化了属性,继承过来的属性值都是一样的
  23. */
  24. Student.prototype = new Person('小名', 10, '男')
  25. Student.prototype.study = function () {
  26. console.log('学习很累')
  27. }
  28. let student = new Student(100)
  29. console.log(student.name) // 小明

借用构造函数实现继承

只继承了属性,没有继承方法

  1. function Person(name, age, sex) {
  2. this.name = name
  3. this.sex = sex
  4. this.age = age
  5. }
  6. Person.prototype.eat = function () {
  7. console.log('人可以吃东西')
  8. }
  9. // 学生构造函数
  10. function Student(name, age, sex, score) {
  11. // 借用构造函数 只继承了属性 没有继承方法
  12. Person.call(this, name, age, sex)
  13. this.score = score
  14. }
  15. let student = new Student('小明',10100)
  16. console.log(student) // 小明

组合继承(原型继承 + 借用构造函数继承)

  1. function Person(name, age, sex) {
  2. this.name = name
  3. this.sex = sex
  4. this.age = age
  5. }
  6. Person.prototype.eat = function () {
  7. console.log('人可以吃东西')
  8. }
  9. // 学生构造函数
  10. function Student(name, age, sex, score) {
  11. // 借用构造函数 只继承了属性 没有继承方法
  12. Person.call(this, name, age, sex)
  13. this.score = score
  14. }
  15. // 改变原型指向 来继承方法
  16. Student.prototype = new Person()
  17. // 学生的方法
  18. Student.protype.sleep = function () {
  19. console.log('睡觉')
  20. }
  21. let stu = new Student('小明', 10, '男', 100)
  22. console.log(stu.name)
  23. console.log(stu.score)
  24. stu.eat()
  25. stu.sleep()

拷贝继承

把一个对象的属性或方法直接复制到另一个对象中

拷贝继承1

  1. var obj1 = {
  2. name: 'zhaosi'
  3. age: 20,
  4. sleep: function () {
  5. console.log("水蕨了")
  6. }
  7. }
  8. var obj2 = {}
  9. for(var key in obj1) {
  10. obj2[key] = obj1[key]
  11. }

拷贝继承2

  1. var obj1 = {
  2. name: 'zhaosi'
  3. age: 20,
  4. sleep: function () {
  5. console.log("水蕨了")
  6. }
  7. }
  8. var obj2 = obj1

1569164446204.png

函数的角色(函数的声明和函数的表达式)

  • 函数的声明

    1. function f1() {
    2. console.log('我是函数声明')
    3. }
    4. f1()
  • 函数表达式

    1. var f2 = function f1() {
    2. console.log('我是函数表达式')
    3. }
    4. f2()

区别

  • 函数声明
    ```javascript if (true) { function f1() {
    1. console.log('我是函数声明 true')
    } } else { function f1() {
    1. console.log('我是函数声明 false')
    } }

/* 在谷歌中:我是函数声明 true 在ie8中:我是函数声明 false

  1. 因为:
  2. 函数的声明会把函数声明提前的,会之前后面的

*/ f1()

  1. - 函数表达式
  2. ```javascript
  3. var ff
  4. if (true) {
  5. ff = function f1() {
  6. console.log('我是函数声明 true')
  7. }
  8. } else {
  9. ff = function f1() {
  10. console.log('我是函数声明 false')
  11. }
  12. }
  13. /*
  14. 在谷歌中:我是函数声明 true
  15. 在ie8中:我是函数声明 true
  16. */
  17. ff()

函数中的this指向

普通函数中的this是谁

  1. function f1() {
  2. console.log(this)
  3. }
  4. // 顶级对象window
  5. f1()

定时器方法中的this是谁

  1. setInterval(() => {
  2. // 顶级对象
  3. console.log(this)
  4. }, 1000)

构造函数中的this

  1. function Person () {
  2. console.log(this)
  3. }
  4. // 因为new Person 会返回一个当前对象 所以 指向的是构造函数中的this实列对象
  5. var per = new Person()
  6. console.log(per)
  7. // Person {}
  8. // Person {}
  9. // 构造函数中的this就是实例对象

原型对象中的this指向

  1. function Person () {
  2. console.log(this) // 实列对象
  3. this.sayHi = function () {
  4. console.log(this) // 实例对象
  5. }
  6. }
  7. Person.prototype.eat = function () {
  8. console.log(this) // 实列对象
  9. }
  10. var per = new Person()
  11. console.log(per)
  12. per.sayHi()
  13. per.eat()

函数也是对象,对象不一定是函数

  • 函数:会有prototype

    因为函数的__proto__constructor指向的是Function()

    所以,所有的函数都是Function的构造函数创建出来的实列对象

  • 对象:会有__proto__

  1. function Person1 () {
  2. }
  3. console.dir(Person)
  4. /*
  5. ƒ Person()
  6. arguments: null
  7. caller: null
  8. length: 0
  9. name: "Person"
  10. prototype: {constructor: ƒ} // 存在 是函数
  11. __proto__: ƒ () // 存在 是对象
  12. apply: ƒ apply()
  13. arguments: (...)
  14. bind: ƒ bind()
  15. call: ƒ call()
  16. caller: (...)
  17. constructor: ƒ Function()
  18. */
  1. console.dir(Math)
  2. // 有__proto__ 没有prototype