二十一.继承方法
JS实现继承的几种方式:
1、属性拷贝(混入式继承)
特点:如果属性的值是引用类型的数据, 子对象和父对象共享同一份数据, 修改其中一个会影响另一个
var obj = {name : 'zs',age : 20,friends:['小明','小红']};
var obj1 = {}; // 需求:obj1获取obj的属性
for(var key in obj){
obj1[key] = obj[key];
}
obj1.friends.push('老王');// 修改了obj1的friends对obj的friends会有影响,因为他们存储的是同一个数组的地址
console.log(obj1);
console.log(obj);
2、原型式继承
Son.prototype = Father.prototype(父构造函数的原型对象赋值给子构造函数的原型对象)
创建出来的对象, 构造器属性, 默认指向父构造函数
无法通过构造器属性进行修改
不能获取实例属性/方法, 只能获取父构造函数原型对象的属性和方法
// 创建父构造函数
function SuperClass(name){
this.name = name;
this.showName = function(){
alert(this.name);
}
}
// 设置父构造器的原型对象
SuperClass.prototype.showAge = function(){
console.log(this.age);
}
// 创建子构造函数
function SubClass(){
}
// 设置子构造函数的原型对象实现继承
SubClass.prototype = SuperClass.prototype;(关键在这里!!!!!)
var child = new SubClass()
3、原型链继承
子构造函数.prototype = new 父构造函数()
无法传递参数给父构造函数-13
继承过来的实例属性会成为原型属性,
对创建出来的对象存在数据共享的问题
// 创建父构造函数
function SuperClass(){
this.name = 'liyajie';
this.age = 25;
this.showName = function(){
console.log(this.name);
}
}
// 设置父构造函数的原型
SuperClass.prototype.friends = ['小名', '小强'];
SuperClass.prototype.showAge = function(){
console.log(this.age);
}
// 创建子构造函数
function SubClass(){
}
// 实现继承
SubClass.prototype = new SuperClass();
// 修改子构造函数的原型的构造器属性
SubClass.prototype.constructor = SubClass;
var child = new SubClass();
console.log(child.name); // liyajie
console.log(child.age);// 25
child.showName();// liyajie
child.showAge();// 25
console.log(child.friends); // ['小名','小强']
// 当我们改变friends的时候, 父构造函数的原型对象的也会变化
child.friends.push('小王八');
console.log(child.friends);["小名", "小强", "小王八"]
var father = new SuperClass();
console.log(father.friends);["小名", "小强", "小王八"]
4、借用构造函数继承
使用call和apply借用其他构造函数的成员
可以解决给父构造函数传递参数的问题, 但是获取不到父构造函数原型上的成员.
也不存在共享问题
只能获取实例属性和方法, 不能获取原型属性和方法
// 创建父构造函数
function Person(name){
this.name = name;
this.freinds = ['小王', '小强'];
this.showName = function(){
console.log(this.name);
}
}
// 创建子构造函数
function Student(name){
// 使用call借用Person的构造函数
Person.call(this, name);
}
// 测试是否有了 Person 的成员
var stu = new Student('Li');
stu.showName(); // Li
console.log(stu.friends); // ['小王','小强']
5、组合继承
借用构造函数 + 原型式继承
解决了 父构造函数的属性继承到了子构造函数的实例对象上了,
继承了父构造函数原型对象上的成员
解决了给父构造函数传递参数问题
// 创建父构造函数
function Person(name,age){
this.name = name;
this.age = age;
this.showName = function(){
console.log(this.name);
}
}
// 设置父构造函数的原型对象
Person.prototype.showAge = function(){
console.log(this.age);
}
// 创建子构造函数
function Student(name){
Person.call(this,name);
}
// 设置继承
Student.prototype = Person.prototype;
Student.prototype.constructor = Student;
6、 借用构造函数 + 深拷贝
这样就将Person的原型对象上的成员拷贝到了Student的原型上了,
这种方式没有属性共享的问题
function Person(name,age){
this.name = name;
this.age = age;
this.showName = function(){
console.log(this.name);
}
}
Person.prototype.friends = ['小王','小强','小王八'];
function Student(name,25){
Person.call(this,name,25); // 借用构造函数(Person)
}
deepCopy(Student.prototype,Person.prototype);// 使用深拷贝实现继承
Student.prototype.constructor = Student;
二十二.团队合作的经验
二十三.通宵经历(不是玩的)
二十四.课外项目(自己瞎做的那种)
二十五.为什么学前端?
二十六.有没有参赛或者除了学校课程内容外的经验?应该是想知道有没有合作经验
二十七.原型与原型链
原型:
①所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象
②所有函数都有一个prototype(原型)属性,属性值是一个普通的对象
③所有引用类型的__proto__属性指向它构造函数的prototype
原型链:
当访问一个对象的某个属性时,会先在这个对象本身属性上查找,
如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,
如果还没有找到就会再在构造函数的prototype的__proto__中查找,
这样一层一层向上查找就会形成一个链式结构,我们称为原型链。
拓展:js中的数据类型有以下几种:
Number Boolean undefined Object Function String Null
基本类型:Number Boolean String undefined null
引用类型:Object Function
二十八.辗转相除法
辗转相除法又名欧几里得算法,目的是求出两个正整数的最大公约数。
function remainder(m,n){
var r = 0;//定义变量存储余数
while (m % n != 0){
r = m % n;
m = n;//把除数 n 当做下一轮的被除数
n = r;//把余数 r 当做下一轮的除数
}
//当余数为0时,最后一个除数就是所求的最大公约数
return n;
}
console.log(remainder(350,505));
二十九.数组转字符串
toString() 将数组转换成一个字符串(var s = a.toString();)
toLocalString() 把数组转换成本地约定的字符串(var s = a.toLocalString();)
join() 将数组元素连接起来以构建一个字符串(var s = a.join("==");)
拓展:
split() 方法把字符串转换为数组。
split() 方法是 String 对象方法,与 join() 方法操作正好相反。(var a = s.split("==");)
三十.二级下拉菜单
Js:
window.onload=function(){
var aLi=document.getElementById("nav").getElementsByTagName("li");
for(var i=0; i<aLi.length;i++){
aLi[i].onmouseover=function(){
this.children[1].style.display='block';//选取当前li元素的第二个子元素
}
aLi[i].onmouseout=function(){
this.children[1].style.display='none';
}
}
}
Jq:
$(function(){
$(".banner>ul>li").mouseenter(function(){
$(this).find("ul").css("display","block");
});
// 给div下的一级菜单li注册事件,鼠标进入显示该li下的二级菜单的ul
$(".banner>ul>li").mouseleave(function(){
$(this).find("ul").css("display","none");
});
// 给div下的一级菜单li注册事件,鼠标离开隐藏该li下的二级菜单的ul
});
拓展更多面试题(100道前端面试题练手):
1、前端近年面试题(1)
2、前端近年面试题(2)
3、前端近年面试题(3)
4、前端近年面试题(4)
5、前端近年面试题(5)
6、前端近年面试题(6)
7、前端近年面试题(7)
8、前端近年面试题(8)
9、前端近年面试题(9)