一、继承

1、原型继承

  1. // 1、原型继承
  2. // 需求:有A类、B类,想要让B所有的实例继承A类私有的和公有的属性和方法
  3. // 利用原型继承:让B类的原型指向A类的实例(因为A类的实例上边,既有A类的私有属性和方法,也可以通过__proto__找到A类原型上的属性和方法)
  4. // IE中不允许这么更改原型
  5. function A () {
  6. this.a = "a";
  7. };
  8. A.prototype.getA = function () {
  9. console.log("A类的公有方法getA()")
  10. };
  11. function B () {
  12. this.b = "b";
  13. };
  14. B.prototype = new A();
  15. var b1 = new B();
  16. console.log(b1);
  17. console.log(b1.a);
  18. console.log(b1.getA);

2、中间类继承

  1. // 2、中间类继承
  2. // 需求:,某些实例并不属于某类,但是想用该类原型上的方法;
  3. // 我们可以手动更改实例的__proto__,让他指向该类的原型
  4. function fn() {
  5. // console.dir(arguments.sort); // undefined 由于arguments类数组对象中没有sort属性
  6. console.dir(arguments.__proto__); // Object
  7. arguments.__proto__ = Array.prototype;
  8. var res = arguments.sort(function (a,b) {
  9. return a-b;
  10. })
  11. return res;
  12. }
  13. var r = fn(9, 7, 5, 3, 1);
  14. console.log(r);

3、call继承

  1. // call()方法,用来改变this指向
  2. // call继承
  3. // 需求:A类和B类,想要让B类的实例用有A类的私有属性
  4. // 可以让A当成普通函数执行,把里面的this指向改为B类的实例(让A类給B类的实例中添加属性)
  5. function A() {
  6. this.a = "a";
  7. this.x = 100;
  8. };
  9. function B() {
  10. A.call(this);
  11. this.b = "b";
  12. this.y = 200;
  13. }
  14. var b = new B();
  15. console.log(b);

4、寄生结合继承

  1. // 寄生组合继承
  2. // A类、B类,B类想要继承A类的私有和公有
  3. // call()方法继承私有属性; 利用一个空对象接受某个原型身上的属性,再这个对象赋值给需要继承的原型上
  4. function A() {
  5. this.a = "a";
  6. this.x = 100;
  7. }
  8. A.prototype.getA = function () {
  9. console.log("A");
  10. }
  11. function B() {
  12. A.call(this);
  13. this.b = "b";
  14. this.y = 300;
  15. }
  16. /* var obj = {};
  17. obj.__proto__ = A.prototype;
  18. B.prototype = obj; */
  19. // Object.create();
  20. B.prototype = Object.create(A.prototype); // 创建一个新对象,并将其值设置为B.prototype;
  21. // 该新对象的__proto__指向A.prototype
  22. console.log(B.prototype.prototype);
  23. var b = new B();
  24. console.log(b);
  25. console.log(b.getA());

二、改变this指向的方法 :call、apply、bind

this指向不可以手动更改

  1. // this指向不可以手动更该
  2. var name = "window";
  3. function fn() {
  4. this = 100;
  5. console.log(this); // 报错
  6. }
  7. fn();

1、call

  1. // call(); 方法更改this指向
  2. var name = "window";
  3. function fn(x, y) {
  4. console.log(this.name);
  5. return x + y;
  6. };
  7. var obj = {
  8. name: "objName",
  9. age: "18"
  10. };
  11. // 第一个参数:更改的this指向
  12. // 第二个参数:
  13. //
  14. fn.call(obj, 1, 3);
  15. /* 执行过程
  16. 1、通过原型链找到Function.prototype 上的call();方法
  17. 2、找到之后,让fn 执行call();
  18. 3、执行时,需要把函数内部的this指向改变为call()的第一个参数
  19. */
  20. // call(); 传递第一个参数的特殊情况
  21. // 非严格模式下:不传参、null、undefined this都指向window
  22. // 严格模式下:不传参 this指向undefined;undefined this指向undefined;null this指向null。

111 关于call();方法的坑题

关于Function.prototype

这是一个空函数 Function.prototype();没有执行结果 返回值为undefined

  1. Function.prototype是一个空函数
  2. ƒ () { [native code] } // 返回值
  3. Function.prototype();
  4. undefined // 函数执行的返回值
  1. function fn1(){
  2. console.log(1);
  3. }
  4. function fn2(){
  5. console.log(2);
  6. }
  7. fn1.call(fn2);
  8. fn1.call.call(fn2);
  9. Function.prototype.call(fn1);
  10. Function.prototype.call.call(fn1);

答案

  1. // fn1.call(fn2);
  2. function call (obj,...ary) { // obj = fn2 this = fn1
  3. obj.$fn = this; // fn2.$fn = fn1
  4. obj.$fn(...ary); // fn2.$fn()相当于函数fn1(); ==> 1
  5. }
  6. // fn1.call.call(fn2); // call(); 相当于fn2.$fn();中this指向fn2
  7. function call (obj,...ary) { // obj = fn2 this = fn1.call obj = window this = fn2
  8. obj.$fn = this; // fn2.$fn = call() window.$fn2 = fn2
  9. obj.$fn(...ary); // fn2.$fn()相当于函数call(); window.$fn2();相当于函数fn2()执行 ==>2
  10. }
  11. // Function.prototype是一个空函数
  12. // ƒ () { [native code] } // 返回值
  13. // Function.prototype();
  14. // undefined // 函数执行的返回值
  15. // Function.prototype.call(fn1);
  16. function call (obj,...ary) { // obj = fn1 this = Function.prototype
  17. obj.$fn = this; // fn1.$fn = Function.prototype
  18. obj.$fn(...ary); // fn1.$fn()相当于函数Function.prototype();
  19. // Function.prototype是一个空函数 ==>没有结果
  20. }
  21. // Function.prototype.call.call(fn1); // call();相当于fn1.$fn();其中的this指向fn1
  22. function call (obj,...ary) { // obj = fn1 this = Function.prototype.call obj = window this = fn1
  23. obj.$fn = this; // fn1.$fn = Function.prototype.call window.$fn = fn1
  24. obj.$fn(...ary); // fn1.$fn()相当于函数call window.$fn1();相当于函数fn1()执行

2、apply

  1. // apply();
  2. var name = "window";
  3. function fn(x, y) {
  4. console.log(this.name);
  5. return x + y;
  6. };
  7. var obj = {
  8. name: "objName",
  9. age: "18"
  10. };
  11. // 第一个参数:更改的this指向
  12. // 第二个参数:以数组(类数组)形式进行传参
  13. // apply(); 和call(); 传形式不同
  14. fn.apply(obj, [1, 3]);

3、bind

  1. // bind(); 预处理this指向,
  2. // 只是预先处理了this指向,并不能让函数执行,
  3. // 想要让函数执行:就再 调用一次返回值;或者给函数绑定一个触发事件
  4. // bind(); 返回值为更改this指向后的函数
  5. var name = "window";
  6. function fn(x, y) {
  7. console.log(this.name);
  8. return x + y;
  9. };
  10. var obj = {
  11. name: "objName",
  12. age: "18"
  13. };
  14. // 第一个参数:更改的this指向
  15. // 第二个参数:
  16. //
  17. fn.bind(obj, 1, 3);
  18. fn.bind(obj, 1, 3)(); // 改边this指向后的函数fn执行;

4、封装call(); 方法

  1. Function.prototype. Mycall = function (obj, ...arg) {
  2. obj = obj || window;
  3. var res;
  4. obj.$fn = this; // 函数fn赋值給obj.$fn; 并且給obj添加了属性$fn
  5. res = obj.$fn(...arg); // obj.$fn();执行的时候this指向obj(达到了改变this指向的目的)
  6. delete obj.$fn; //
  7. return res; // 把函数obj.$fn()的返回值暴漏出去;(也就是fn()执行的返回值)
  8. }
  9. var obj = {name : "objname", age:18};
  10. function fn(x, y) {
  11. console.log(this.name);
  12. return x+y;
  13. }
  14. // fn(3, 4);
  15. fn. Mycall(obj, 1, 2);
  16. var obj2 = {
  17. name : "123",
  18. age : 19
  19. };
  20. fn. Mycall(obj2, 3, 2);