/在学习继承之前先了解一下call和apply/
1.call与apply
*/
call与apply : 改变this的指向
事件处理函数中 this----->触发事件的对象
普通函数中 this------>window
构造函数中 this ----> 实例对象
实例对象的方法中 this---对象
*/
//1. call
//sum.call(指向this的指向)
function sum(){
console.log(this);//window
}
sum();
sum.call(sum);//sum函数
sum.call(1); //Number {1}
sum.call("1"); //String {"1"}
sum.call([]); //[]
//有参数 sun.call(this的指向,参数1,参数2,....)
function sun(a,b){
console.log(this);//window
console.log(a+b);
}
sun(10,20);//30
sun.call(document,40,50); //document 90
var obj1 = {
"name":"如花",
"toString":function(){
console.log(this.name);
}
}
var obj2 = {
"name":"似玉",
"toString":function(){
console.log(this.name);
}
}
obj2.toString.call(obj1); //如花
//sum.apply(this的指向,[参数1,参数2]);
function sun(a,b){
console.log(this);
console.log(a+b);
}
sun.apply(document,[10,20]);
//可以用apply找出数组最大值
var arr = [5,7,9,2,6,0,4,1];
console.log(Math.max.apply(1,arr));
*/call和apply的作用和用法是一样的,只是apply在传参的时候形式不一样,参数要用中括号扩上*/
2.面向对象的几种继承方式
(1)原型链继承
//1.声明父类构造函数
function Student(name,id){
this.name = name;
this.id = id;
this.arr = [1,2,3];
}
Student.prototype.study = function(){
console.log("好好睡觉,好好长身体,好好休息");
}
//2.声明一个子类构造函数
function SmallStudent(){
this.homeWork = function(){
console.log("作业太少");
}
}
//3.继承操作 原型链继承 子类的原型对象指向父类的实例对象
SmallStudent.prototype = new Student("小明",007);
var ss1 = new SmallStudent();
console.log(ss1); SmallStudent {homeWork: ƒ}
ss1.study(); //好好睡觉,好好长身体,好好休息
console.log(ss1.name); //小明
console.log(ss1.arr); //[1,2,3]
ss1.arr.push(4);
console.log(ss1.arr); //[1,2,3,4]
var ss2 = new SmallStudent();
console.log(ss2.name); //小明
console.log(ss2.arr); //[1,2,3,4]
*/原型链,先找实例对象本身,有就用自己的,没有就找实例对象中的__proto__(prototype),依次往父级找,一直找不到返回undefined*/
*/缺点:不能传参,如果继承下来引用类型数据,一改全改*/
(2)对象冒充继承
//1.声明父类构造函数
function Student(name,id){ //window---->SmallStudent
this.name = name;
this.id = id;
this.arr = [1,2,3];
}
Student.prototype.study = function(){
console.log("好好睡觉,好好长身体,好好休息");
}
//2.声明一个子类构造函数
function SmallStudent(name,id){
/*
this.name = name;
this.id = id;
this.arr = [1,2,3];
*/
//创建一个空对象 this--空对象
//this--->
Student.call(this,name,id);//改变Student里面的this指向
this.homeWork = function(){
console.log("作业太少");
}
}
var ss1 = new SmallStudent("小红",007);
console.log(ss1);//SmallStudent {name: "小红", id: 7, arr: Array(3), homeWork: ƒ}
ss1.arr.push(4);
console.log(ss1.arr);// [1, 2, 3, 4]
var ss2 = new SmallStudent("小明",007);
console.log(ss2);//SmallStudent {name: "小明", id: 7, arr: Array(3), homeWork: ƒ}
console.log(ss2.arr);//[1, 2, 3]
ss1.study(); //Uncaught TypeError: ss1.study is not a function不能继承原型对象中的内容
*/缺点:解决了不能传参的问题,但是新的问题是继承不了原型中的内容*/
(3)组合继承: 对象冒充(构造函数)+原型继承(原型对象)
//1.声明父类构造函数
function Student(name,id){ //window---->SmallStudent
this.name = name;
this.id = id;
this.arr = [1,2,3];
}
Student.prototype.study = function(){
console.log("好好睡觉,好好长身体,好好休息");
}
//2.声明一个子类构造函数
function SmallStudent(name,id){
//对象冒充继承:继承构造函数中个的内容
Student.call(this,name,id);
this.homeWork = function(){
console.log("作业太少");
}
}
//原型链继承;继承原型对象中的内容
SmallStudent.prototype = new Student();
var ss1 = new SmallStudent("小美","007");
console.log(ss1);
ss1.study();//好好睡觉,好好长身体,好好休息
4.面向对象继承的实例
拖拽+控制范围
<div id="box1"></div>
<div id="box2"></div>
<script>
//创建构造函数
//属性,方法
//创建父函数,具有拖拽效果
function Drag(id) {
this.oDiv = document.getElementById(id);
this.x = 0;
this.y = 0;
var _this = this;
this.oDiv.onmousedown = function (ev) {
_this.mouseDown(
);
document.onmousemove = function (ev) {
_this.mouseMove();
}
document.onmouseup = function () {
_this.mouseUp();
}
return false;
}
}
Drag.prototype = {
"mouseDown": function () {
var ev = window.event || ev;
this.x = ev.clientX - this.oDiv.offsetLeft;
this.y = ev.clientY - this.oDiv.offsetTop;
},
"mouseMove": function () {
var ev = window.event || ev;
var l = ev.clientX;
var t = ev.clientY;
this.oDiv.style.top = t - this.y + "px";
this.oDiv.style.left = l - this.x + "px";
},
"mouseUp": function () {
document.onmousemove = document.onmouseup = null;
}
}
//进行继承连接,父元素的实例对象赋值给子元素的原型
Limit.prototype= new Drag("box1");//原型链继承
//创建子函数,对象冒充继承Drag的属性和方法---
function Limit(id){
Drag.call(this,id);
}
//添加Limit比Drag多的方法,限制拖拽范围
Limit.prototype.mouseMove=function(ev){
var ev = window.event||ev;
var l=ev.clientX-this.y;
var t=ev.clientY-this.x;
if(l<0){l=0;}
if(t<0){t=0;}
if(l>document.documentElement.clientWidth-this.oDiv.offsetWidth){
l=document.documentElement.clientWidth-this.oDiv.offsetWidth+"px";
}
if(t>document.documentElement.clientHeight-this.oDiv.offsetHeight){
t=document.documentElement.clientHeight-this.oDiv.offsetHeight+"px";
}
this.oDiv.style.top=t+"px";
this.oDiv.style.left=l+"px";
}
new Drag("box1");//box1可以拖拽
new Limit("box2");//box2在拖拽的基础上还可以限制拖拽的范围