一省:HTML
12. img标签的alt和title有什么不同?
1.alt:
- 当图片加载不出来的时候,就会在图片未显示的地方出现一段 alt 设置的属性内容。
- 浏览器的搜索引擎可以通过 alt 属性的文字描述来获取图片。
2.title: - title是鼠标放在图片上面时显示的文字,title 是对图片的描述和进一步的说明。
二省: CSS
12. 媒体查询是什么?
css中媒体查询使用@media实现,@media 可以针对不同的屏幕尺寸设置不同的样式,特别是如果你需要设置设计响应式的页面,@media 是非常有用的。当你重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面。如:
@media screen and (max-width: 300px) {
body {
background-color:lightblue;
}
}
三省:JavaScript
12. 原型链和继承的六种实现方式
原型链: 对象的原型对象也有自己的原型(__ptoto__),即
function Person(){
}
var person = new Person()
console.log(person.__proto__);//对象的原型
console.log(person.__proto__.__proto__);//对象原型的原型
...
相应的,原型的原型还有原型,直到原型指向Object.prototype,而Object的原型指向null,这种原型的链条就叫原型链
console.log(Object.prototype.__proto__)//null
有一个老图,可以参考:
继承: 子类继承父类的特征和行为,使得子类具有父类的属性和方法。在js中,有以下6种继承方式:
1. 原型链继承
// 父类: 公共属性和方法
function Father(name) {
this.name = name || "zosi"
this.arr = [1]
}
Father.prototype.say = function(){
console.log(this.name + " say hello world!");
}
// 子类: 独有属性和方法
function Child(height) {
this.height = height || 180
}
//继承父类
Child.prototype = new Father()
Child.prototype.run = function() {
console.log(this.name + " running! " + this.height);
}
var child1 = new Child("lemon", 170)
var child2 = new Child(160)
child1.say();//zosi say hello world!
child2.run();//zosi running! 160
child1.arr.push(2)
console.log(child1.name, child2.arr, child1, child2);//zosi [1, 2] Child {height: 'lemon'} Child {height: 160}
缺点:
- 打印子类实例时,继承的属性看不到
- 创建子类实例时,无法传父类的参数
- 子类实例会共享父类的引用类型的参数
2. 借用构造函数继承
// 父类: 公共属性和方法
function Father(name) {
this.name = name || "zosi"
this.arr = [1]
}
Father.prototype.say = function(){
console.log(this.name + " say hello world!");
}
// 子类: 独有属性和方法
function Child(name, height) {
//继承父类
Father.call(this, name)
this.height = height || 180
}
Child.prototype.run = function() {
console.log(this.name + " running! " + this.height);
}
var child1 = new Child("lemon")
var child2 = new Child("Jack", 160)
// child1.say();//报错
child2.run();//Jack running! 160
child1.arr.push(2)
console.log(child1.arr, child2.arr, child1, child2);//[1, 2] [1] Child {name: 'lemon', arr: Array(2), height: 180} Child {name: 'Jack', arr: Array(1), height: 160}
虽然解决了原型链继承的缺点,但是它本身也有缺点:
- 子类无法访问父类原型的方法
3. 组合式继承
// 父类: 公共属性和方法
function Father(name) {
this.name = name || "zosi"
this.arr = [1]
}
Father.prototype.say = function(){
console.log(this.name + " say hello world!");
}
// 子类: 独有属性和方法
function Child(name, height) {
//继承属性
Father.call(this, name)
this.height = height || 180
}
// 继承方法
Child.prototype = new Father()
Child.prototype.run = function() {
console.log(this.name + " running! " + this.height);
}
var child1 = new Child("lemon")
var child2 = new Child("Jack", 160)
child1.say();//lemon say hello world!
child2.run();//Jack running! 160
child1.arr.push(2)
console.log(child1.arr, child2.arr, child1, child2);//[1, 2] [1] Child {name: 'lemon', arr: Array(2), height: 180} Child {name: 'Jack', arr: Array(1), height: 160}
组合继承综合了原型链和借用构造函数。缺点:
- 调用两次父类构造函数。
4. 原型式继承
var person = {
name: "Jack",
friends: ["Marry"]
}
// 方法一:作者-> Douglas Crockford - 2006
function object(o){
function F(){
}
F.prototype = o
return new F()
}//object()对传入的对象进行了一次浅拷贝
var p1 = object(person)
p1.friends.push("Jane")
var p2 = object(person)
p2.friends.push("Larry")
console.log(p1.friends);//['Marry', 'Jane', 'Larry']
// 方法二:Object.setPrototypeOf()
function creatObject(o) {
let newObj = {
}
Object.setPrototypeOf(newObj, o)
return newObj
}
var p1 = creatObject(person)
p1.friends.push("Bob")
var p2 = creatObject(person)
p2.friends.push("Chansen")
console.log(p1.friends);//['Marry', 'Bob', 'Chansen']
// 方法三:ES5 -> Object.create() 接受两个参数,第二个参数可以添加或者覆盖属性
var p1 = Object.create(person)
p1.friends.push("Sale")
var p2 = Object.create(person, {
name: {
value: "Mieba"
}
})
p2.friends.push("Jordan")
console.log(p1.friends, p2.name);// ['Marry', 'Sale', 'Jordan'] 'Mieba'
原型式继承非常适合不需要单独创建构造函数的场景,但是缺点也很明显:
- 无法传参
- 引用类型会在实例间共享
5. 寄生式继承
var person = {
name: "Jack",
friends: ["Marry"],
run: function() {
console.log("run run run!");
}
}
function createPerson(obj){
let p = Object.create(obj)
p.say = function() {
console.log("say hello world!");
}
return p
}
var p1 = createPerson(person)
p1.run();//run run run!
p1.friends.push("Jerry")
var p2 = createPerson(person)
p2.say();//say hello world!
console.log(p1.name, p2.friends);//Jack ['Marry', 'Jerry']
寄生式继承缺点与原型式继承一致。
6. 寄生组合式继承(推荐)
//封装继承方法
function inheritPrototype(subType, superType) {
let prototype = Object.create(superType.prototype);//创建对象
prototype.constructor = subType;//增强对象
subType.prototype = prototype;//赋值对象
}
// 父类: 公共属性和方法
function Father(name) {
this.name = name || "zosi"
this.arr = [1]
}
Father.prototype.say = function(){
console.log(this.name + " say hello world!");
}
// 子类: 独有属性和方法
function Child(name, height) {
//继承属性
Father.call(this, name)
this.height = height || 180
}
// 继承方法
inheritPrototype(Child, Father)
Child.prototype.run = function() {
console.log(this.name + " running! " + this.height);
}
var child1 = new Child("lemon")
var child2 = new Child("Jack", 160)
child1.say();//lemon say hello world!
child2.run();//Jack running! 160
child1.arr.push(2)
console.log(child1.arr, child2.arr, child1, child2);// [1, 2] [1] Child {name: 'lemon', arr: Array(2), height: 180} Child {name: 'Jack', arr: Array(1), height: 160}
继承的最佳模式。