js 是弱类型语言;
面向对象有三个特征:
封装 继承 多态
找寻机制 -> 原型链;
链:作用域链 -> 原型链;
继承的限制 => 只有在使用构造函数和原型编程时可以使用继承;
1.克隆是继承;
2.权限式继承;
构造函数的继承:function Father(name, age, money) { this.name = name;this.age = age;this.money = money;}var father = new Father("王健林", "60", "100亿");console.log(father);function Son(name, age, money) {Father.call(this, name, age, money);}function Son() {Father.apply(this, arguments);}var son = new Son("王思聪", "31", "50亿");console.log(son);Math.min(1, 2, 3, 4, 5, 6, 7)Math.min.apply(false, [1, 2, 3, 4, 5])call&apply (改变this指向的方法)this指向的两种情况:1.指向函数的调用者;2.在构造函数中,指向实例化对象;3.bind => 在函数创建初期固定this指向;function foo(a, b, c) {console.log(this, a, b, c);}// foo(); // this => window// call 第一个参数就是制定当前函数this指向的;// foo.call({ name: "一个任意对象" }) // 调用// call 制定函数的调用者; foo.apply({ name: "一个任意对象" })// call 和 apply 都是制定函数调用者的方法(在调用时改变函数的this指向的方法);// call 和 apply 的不同;// call(arg1, arg2, arg3, ..., arg10)// call 的第二个及以后的参数和形参一一对应;// foo.call({ name: "一个任意对象" }, 1, 2, 3)// foo.call({ name: "二个任意对象" }, 1, 2, 3)// foo.call({ name: "三个任意对象" }, 1, 2, 3)// foo.call(改变tihis指向,实参1,实参2,...,实参n)// apply 只接受两个参数; apply(arg_this, arg_arguments_array); foo.apply({ name: "一个任意对象" }, [1, 2, 3]);// call,apply 都是在调用函数的时候改变this指向的方法;// call,接受n个参数 第一个参数改变this,其余的参数和形参一一对应// apply,接收两个参数 第一个参数改变this,第二个参数改变arguments对象;原型对象的继承:// 方法有必要复制么 ?// function foo(){// console.log("我执行了");// }// var myFoo = foo;// var myNewFoo = eval("("+foo.toString()+")");// myFoo();// myNewFoo();// 函数体内的代码是不变更的;// 在继承方法的时候,只要拿到函数的地址就可以了;// console.log(foo === myFoo , foo === myNewFoo);function Father() {this.name = "马云";};Father.prototype.show = function () {console.log("马云 : 我不喜欢钱,我对钱没有兴趣");console.log("撒贝宁 : 噗呲... ");}// father => 由构造函数直接负责;var father = new Father();console.log(father);father.show();// 原型的动态性;function Son() {this.hello = function () {console.log("say hello");}};// var son = new Son();// console.log(son);// Son.prototype = Father.prototype;// var son2 = new Son();// console.log(son2);//tip : 在实例化之前一定要完成原型的变更;// var son = new Son();// console.log(son);// 新的方法就必须写在构造函数里了;// Son.prototype.hello = function(){// console.log("say hello");// }// console.log(son);// 原型的赋值;// 循环赋值 => 保留了子集的原型,不用把新的覆盖的方法写在构造函数中;// 遍历父级所有方法;for (var attr in Father.prototype) {Son.prototype[attr] = Father.prototype[attr];}Son.prototype.hello = function () {console.log("say hello");}var son = new Son();console.log(son);原型链的继承:// 原型链// 链 ? 找寻方式;var obj = {};var obj = new Object();console.log(obj);console.log(obj.toString());// 实例化对象找寻某个属性是否存在的过程,在这个过程之中会按照当前对象之中存在的原型指针依次进行查找;// 访问某个属性是解析器做了些啥 ?// 1. 有没有某个属性 ?// 1.1 有 => 返回;// 1.2 没有 => 有没有原型指针;// 1.2.1 有 => 返回;// 1.2.2 没有 => 返回undefined;// function Father() {// }// Father.prototype.hello = function () {// }// function Son() {// }// Son.prototype = new Father();// var son = new Son();// console.log(son);function Father() {}Father.prototype.hello = function () {}function Son() {}// Son.prototype = new Father();// 语义化更清晰了; ES5 的;// Son.prototype = Object.create(Father.prototype);// Son.prototype = Object.create({ name: "hello" });// Object.create();// Object.create 创建一个对象; 这个对象之中有一个指针指向参数对象;// var son = new Son();// console.log(son);// 不要这样;Son.prototype = Object.create(Son.prototype);var son = new Son();console.log(son);// 原型链继承 => 给当前原型对象上添加一个原型指针,让当前原型对象和父级(希望继承的原型上有一个联通方式);