<script >
// js是一 种面向对象的 弱类型的 解释性的语言
//弱类型 声明变量的时候不需要注明数据类型int a = 1; float(强类型) var a = 1.2;
//解释性 解释一句执行一句 编译性 一次性全部翻译完然后再执行
//面向对象 封装 继承 多态(js语言没有多态)
//封装 将一个功能都放在 一个对象里面,只需要向外界暴露一 一个接口, 需要使用的时候直接调接口就可以了 并不需要管底层是怎么实现的
// push向数组的最 后添加一个元素
var arr = [12, 23];
arr.push(15);
//继承:指的是js对象之间的继承如果我们想让一个对象拥有另一个对象的属性或者方法 那么我们就可以让这个对象继承自另一个对象
</script>
继承方式一
<script>
/*1.使用构造函数来实现继承
实现方式:使用ca11等方法使一个对象的thi s指向另一个对象从而让其拥有这个对象的属性和方法
缺点:无法继承父类原型上面的方法 对于子类不需要的方法 每次创建都会拥有浪费内存空间
*/
//有很多构造函数的额情况下,如果需要给所有的构造函数添加属性,那么就需要分别去加
就不便于维护
function Parent(name, age) {
this.name = name;
this.age = age;
this .work = function(){
console.log("我要读书");
}
}
Parent.prototype.test = function(){
console.log(111);
}
Parent.prototype.type = "人类 " ;
var p1 = new Parent("姐姐", 30);
/*function Child(name, age, gender) {
this.name = name;
this.age = age;
}
var c1 = new Child("孩子", 12);
call apply bind 修改this指向的方法
*/
function Child(name, age) {
Parent.call(this, name, age)
}
var c2 = new Child("雪儿", 12);
console.log(c2);
//就是说只是把父类构造函数里面的属性和方法继承了但是父类原型里面的方法继承不了
//c2.test(); // 报错
//创建的child对象并不需要work方法但是每次创建都会有(浪费空间)
c2.work() //执行了函数体
继承方式二
<script>
/*2.原型拷贝继承(混入式继承)
实现方式:使用for- in遍历父类原型里面的所有属性,依次加入子类的原型中
缺点:原型中子类不需要的方法或者属性也继承过来了 占用内存空间
*/
function Parent(name, age) {
this.name = name;
this.age = age;
this.work = function() {
console.log("我要读书学习");
}
}
Parent.prototype.test = function(){
console.log(111);
}
Parent.prototype.type = "人类 " ;
function Child(name, age) {
this.name = name;
this.age = age;
}
//原型对象拷贝
for(var key in Parent . prototype) {
Child.prototype[key] = Parent.prototype[key];
console.log(Parent.prototype[key]);
}
var c1 = new Child(" lisi", 12);
c1.test();
console.log(c1.type);
继承方式三
<script>
/*3.原型链继承
实现方法:利用原型链来实现继承 父类的一个实例化对象作为子类的原型
缺点:子类实例和父类实例的原型对象上有成员的共享问题
*/
function Parent(name, age) {
this.name = name ;
this.age = age;
this.work = function () {
console.log("我要读书");
};
}
Parent.prototype.test = function (){
console.log(111);
};
Parent.prototype.type = "人类";
function Child(name, age) {
this.name = name ;
this.ageage;
}
Child.prototype = new Parent();
console.log(Child.prototype.constructor);
//重新替换原型之后 构造函数并不指向原构造函数,所以要将构造函数指向原函数Child . prototype.constructor = Child;
var c1 = new Child("wangwu", 12);
console.log(c1.type);
c1.test()
//为什么不直接使用Child.prototype = Parent??
//把父类的构造函数直接替换掉子类的原型会导致父类构造函数的私有属性发生变化甚至有些成员 父类构造函数并不需要
child.prototype = Parent;
Child.prototype.study = function() {
console.1og( "好好学习,天天向上");
}
console.dir(Parent);
Parent.study();
</script>
继承方式四
<script >
//4.组合继承(原型链 和cal1继承组合)
function Father() {
this.name = "父亲";
this.run = function() {
console. log(this.name + "我要健身");
}
}
Father.prototype = {
constructon.Father,
type : (local function)(): void
eat : function() {
console.log(this.name + "我要吃饭");
}
}
function Son(age) {
//这个是继承父类构造函数里面的属性或者方法
Father.call(this);
this.age = age;
this.study = function() {
console.log(this.name + "我要学习了");
}
}
//继承父类原型中的成员
Son.prototype = new Father();
Son.prototype.constructor = Son;
Son.prototype.sleep = function() {
console.log(this.name + "我要睡觉 了");
}
var s1 = new Son(12);
//这个是父类构造函数里面的方法
s1.run();
//是父类原型里面的方法
s1.eat();
console.log(s1.type);
//自己构造函数里面的方法
s1.study();
//自己的原型里面的方法
s1.sleep();
</script>
复习
<script>
var obj = {
name = "lisi"
}
/*function test( ) {
console.1og(111);
console.log(this);
this = obj ;//报错,this不能放在赋值复制符号的左边
}
test();
*/
//1.call()
/*语法:函数名.call(this的新指向,原函数的参数1,原函数的参数2, .....)
调用call方法后 会直接执行原函数的函数体
function getSum(n1, n2) {
console.1og(n1 + n2);
console.log(this);
}
getSum(12,12);
getSum.call(obj,12,12);
*/
// 2. apply()
//语法:函数名.apply(this的新指向, 参数数组(数组,伪数组))
//注意apply只有两个参数//调用apply方法后会 直接执行原函数的函数体
// function getSum(n1, n2) {
console.1og(n1 + n2);
console.log(this);
}
// getSum. apply(obj, [12, 24])
// 3. bind()
//语法:函数名.bind(this的新指向, 参数1,参数2, ......
//不会执行修改了this指向后的函数,而是直接作为返回值返回
function getSum(n1, n2) {
console.1og(n1 + n2);
console.log(this);
}
var fn = getSum.bind(obj);
console.log(fn);
fn(12, 12)