【每日十分钟前端】基础篇14,300毫秒点击延迟问题、值和单位px、em、rem、vw/vh、JS如何实现继承

1、[HTML]300 毫秒点击延迟问题?
2、[CSS]值和单位px、em、rem、vw/vh?
3、[JS]JS 如何实现继承?


1、300 毫秒点击延迟问题

产生原因:

在移动端,用这个300ms的时间,去判断用户的操作是要打开连接还是进行双击操作,比如双击缩放。

最早前的网页只给大屏幕设计,苹果在发布首款ihone的时候做做了一些约定,针对这些小屏幕浏览站点的问题,其他移动浏览器都相继复制了多数约定,就包括了双击缩放。

随着移动端的发展,用户对于体验的要求越来越高,这个300ms带来的卡顿就让人难以接受。

解决方案:

禁止缩放。
<meta>标签操作,必须完全禁止用缩放;

initial-scale=1.0, maximum-scale=1.0, user-scalable=0;
非适配移动端的界面,图片或者一段字体很小的文字也无法实现放大查看了。

width=device-width;
Chrome32开始,默认width=device-width的时候禁止缩放页面。
用了这个的页面一般是为移动端设计的页面,默认宽度从980变成了移动端刚刚好的宽度,比如iphone上的300+,消除了在该站点上可能潜在的双击缩放需求。

2、值和单位px、em、rem、vw/vh、vmax/vmin

px

绝对长度单位,像素pixel的缩写,图像显示的基本单元,页面的常用单位,是相对于浏览器屏幕分辨率而言的。

em

相对长度单位,是相对于当前对象内字体大小(父级font-size,未设置时参考浏览器默认字体大小)而言的的。

rem

相对长度单位,css3的新单位,是相对于html根元素字体大小(html的font-size,未设置参考浏览器默认字体大小)而言的。
ie8及之前的版本不可用。

vw/vh、vmax/vmin

基于视口(viewport)的单位;
vw相对于视口的宽度,1vw= 1*(视口宽度/100);
vh相对于视口的高度,1vh= 1*(视口高度/100);
vmin:1vw和1vh中较小的那个;
vmax:1vw和1vh中较大的那个。

3、JS 如何实现继承?

JavaScript主要通过原型链来实现继承,通常继承意味着复制,然而JavaScript默认不会复制对象属性,只是在两个对象之间创建一个关联(类似指针),从而达到可以访问另一个对象的属性和方法。

继承是面向对象技术中的一种概念,与多态、封装共为面向对象的三个基本特征。
继承可以使子类具有父类的属性和方法或者重新定义、追加属性和方法等。
继承是类与类之间的关系,不是对象与对象之间的关系。

构造函数、实例:

构造函数是用来创建对象的函数,也属于函数,区别在于调用方式不同。
通过new操作符来创建它的实例对象的就是构造函数,没有的就是普通函数。

function Funname(){}
var fun1 = new Funname()

fun1这里的Funname是构造函数,fun1叫做Funname的实例。

原型对象

函数有一个prototype属性,指向原型对象。
new了一个新的对象的时候(上述fun1),不做别的操作,可以直接访问原型对象的(funname里面的)属性和方法。
原型对象也有它自己的__proto__
构造函数被声明时,原型对象也一同完成创建,然后挂载到构造函数的prototype属性上。

构造函数,原型对象和实例的关系

函数的prototype->原型对象
原型对象的constructor->函数
实例对象的protoptype->原型对象(允许实例通过该prototype属性访问原型对象中的属性和方法)

sequenceDiagram
Funname(构造函数)->>Funname.prototype(实例原型): prototype
Funname.prototype(实例原型)->>Funname(构造函数): constructor

Funname(构造函数)->>fun1:   
fun1->>Funname.prototype(实例原型): __proto__

Funname.prototype(实例原型)->>Object.prototype: __proto__
Object.prototype->>null: __proto__

Object.prototype->>Object(): constructor
Object()->>Object.prototype: rototype
原型链

上一篇写的原型链,理解了这个就能更好的理解继承问题,也是继承的主要思路。

(1)、原型链继承

让对象实例通过原型链的方法串联起来,当访问目标对象的某一属性是,能顺着原型链进行查找,从而达到类似继承的效果。

将子类子类与父类的原型联系起来(原本父类原型的constructor指向父类的)

//父类
function Parent() {}
//子类
function Child() {}
//继承父类
Child.prototype = new Parent()
//改变constructor指向
Child.prototype.constructor = Child
sequenceDiagram
子类原型prototype->>父类实例new Parent(): prototype
父类实例new Parent()->>父类原型prototype: prototype
父类原型prototype->>子类原型prototype: constructor

优点:
父类方法可以复用。

缺点:
(1)、引用关系,父类的所有引用属性会被所有子类共享,多个子类的话,一个改了,别的都被改了,目标只有一个;
(2)、子类实例不能给父类传值。

(2)、构造继承

在子类构造函数中调用父类构造函数,可以在子类构造函数中使用call()apply()方法。

function Parent(value){
    this.value = value;
}
function Child(value) {
    //继承自Parent,并可传参
    Parent.call(this,value)
}

通过使用call和apply方法,Parent构造函数在为Child的实例创建的新对象的上下文执行了,相当于新的Child实例对象上运行了Parent()函数中的所有初始化代码,导致每个实例都有自己的parentxxx属性。

优点:
(1)、子类构造函数可以向父级传参;
(2)、父级的引用类型不共享。

缺点:子类不能访问父类原型上(Parent.prototype)定义的方法,因此所有方法属性都写在构造函数中,每次创建实例都会被初始化。

(3)、组合继承

使用了call在子类构造函数中调用父类构造函数;
综合了原型链继承和构造函数继承的有点。

function Parent(value) {
    this.value = value;
}
Parent.prototype.getValue = function() {
    console.log(this.value);
}
function Child(value) {
    //继承父类属性
    Parent.call(this, value)
}
//继承父类方法
Child.prototype = new Parent();

优点:
(1)、父类方法可以复用;
(2)、可以在子构造函数中向父级构造函数中传参;
(3)、解决了原型链继承中的缺点,引用属性不会被共享。

缺点:父级调用了两次(创造子类原型和实例的时候都会被调用一次),初始化了两次,子类原型上会存在父类实例属性。

(4)、原型式继承

对参数对象的一种浅复制

let Parent = {};
function returnParent(obj) {
    function Fun() {}
    Fun.property = obj;
    return new Fun()
}
let child = returnParent(Parent)

优点:父类方法可复用。

缺点:
(1)、父类的引用会被所有子类所共享
(2)、子类实例不能向父类传值

(5)、寄生式继承

使用原型式继承对一个目标对象进行浅复制,增强这个复制的内容

let Parent = {};
function returnParent(obj) {
    function Fun() {
        Fun.property = obj;
    }
}
//再次复制
function returnParentAga(obj) {
    let clone = returnParent(obj);
    clone.getValue = function() {}
    return clone;
}
let child = returnParentAga(Parent)
(6)、寄生组合继承
let Parent = {}
function returnParent(obj) {
    function Fun() {};
    Fun.prototype = obj;
    return new Fun();
}
function createParentProto(child, parent) {
    // 复制prototype
    let proto = returnParent(parent.prototype)
    // 链接child
    proto.constructor = child
    //赋值
    child.prototype = protp
}
functoin Parent () {};
function Child() {
    Parent.call(this)
}
createParentProto(Child, Parent)
let child = new Child(){}

也可根据Object.create(Parent.prototype)创建一个新的原型对象

function Parent() {}
Parent.prototype.getValue = function() {}
function Child(value) {
    Parent.call(this)
}
Child.prototype = Object.create(Parent.prototype, {
    constructor: {
        value: Child,
        enumerable: false, // 不可枚举该属性
        writable: true, // 可改写该属性
        configurable: true // 可用 delete 删除该属性
    }
})

优点:
(1)、父级方法可以复用;
(2)、只调用一次父级构造函数;
(3)、子级可以向父级传参;
(4)、父级的引用属性不会被共享。

继承关系判断:
(1)、instanceof

xxx是不是xxx的实例。
通过原型链查找来判断继承关系,因此只能用来判断引用类型,对基本类型无效。

(2)、Object.prototype.isPrototypeOf(obj)

还可以利用Object.prototype.isPrototypeOf来间接判断继承关系,该方法用于判断一个对象是否存在于另一个对象的原型链上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值