双飞翼 圣杯布局
<!--圣杯布局-->
<style>
p {
margin: 0px;
padding: 0px;
}
#container {
overflow: hidden;
padding-left: 200px;
padding-right: 150px;
}
#container p {
float: left;
}
#container .center {
background-color: red;
width: 100%;
}
#container .left {
background-color: yellow;
width: 200px;
position: relative;
left: -100%;
margin-left: -200px;
}
#container .right {
background-color: green;
width: 150px;
margin-left: -150px;
position: relative;
left: 150px;
}
</style>
<body>
<div id="container" class="clearfix">
<p class="center">我是中间</p>
<p class="left">我是左边</p>
<p class="right">我是右边</p>
</div>
</body>
<!--双飞翼布局-->
<style>
p {
margin: 0px;
padding: 0px;
}
#container {
width: 100%;
float: left;
}
#container .center {
background-color: red;
margin-left: 200px;
margin-right: 150px;
}
.left {
background-color: yellow;
width: 200px;
margin-left: -100%;
float: left;
}
.right {
background-color: green;
width: 150px;
float: left;
margin-left: -150px;
}
</style>
<body>
<div id="container" class="clearfix">
<p class="center">我是中间</p>
</div>
<p class="left">我是左边</p>
<p class="right">我是右边</p>
</body>
继承实现常用方式
- 构造函数继承
function abc(name) {
this.name = name;
this.fun = function () {
console.log('zhelishi')
}
}
var newAbc = function () {
abc.apply(this, arguments);
}
var one = new newAbc('lianjie');
console.log(one.fun())
- 原型链继承
function abc(){
}
abc.prototype.name = 'lianjie'
function childs(){
}
childs.prototype = new abc()
var child = new childs();
console.log(child.name,'---') //lianjie ---
- 组合继承 原型链+ 构造函数
function abc(name) {
this.name = name;
}
abc.prototype.fun = function () {
console.log('fun-abc')
}
var ddd = function () {
abc.call(this, ...arguments)
}
ddd.prototype = new abc();
var ccc = new ddd('lianjie');
console.log(ccc.fun(),'----ccc---')
可以看到这里是有点问题的,如果子实例去除 name属性,还能访问到父级name,因为abc构造函数执行了两次。
4.原型式继承
同时也是Object.create 原理
function parents(name){
this.name = name
}
parents.prototype.fun = function(){
console.log('fun--fun')
}
var todo = function(newO){
var func = function(){}
func.prototype = newO;
return new func()
}
var newChild = new parents()
var newChild2 = todo(newChild)
console.log(newChild2.fun())
5.寄生式
function parents(name){
this.name = name
}
parents.prototype.fun = function(){
console.log('fun--fun')
}
var todo = function(newO){
var func = function(){}
func.prototype = newO;
return new func()
}
var newChild = new parents()
var taoyiceng = function(){
var newChild2 = todo(newChild)
newChild2.name = '12323nlk'
return newChild2
}
var bbb = taoyiceng()
console.log(bbb.name); //12323nlk
6.最终 寄生+组合
var Person = function(age){
this.age = age
}
Person.prototype.add = function(){
console.log('add')
}
function object(obj){
function F(){}
F.prototype = obj;
return new F();
}
var obj = object(Person.prototype) //其实就是复制了父级的prototype 再new了一个实例。
function Sub(age) {
Person.call(this); // 这个继承了父类构造函数的属性
this.age = age;
} // 解决了组合式两次调用构造函数属性的特点
Sub.prototype = obj;
var child = new Sub('12313');
obj.constructor = Sub;
console.log(child instanceof Person); //true
console.log(child.age,'---') //12313
和组合继承比的好处就是不用new 两次 Person 父级。 在子实例删除父子都有的属性,不会再到父级获取。
怎么判断一个数据的类型
- typeof
//能区分
console.log(typeof 123); //number
console.log(typeof '223'); //string
console.log(typeof function a() { console.log(123123) }); //function
console.log(typeof 2172141653n); //bigint
console.log(typeof Symbol("foo")) //symbol
console.log(typeof undefined) //undefined
//无法区分
console.log(typeof null) //object
console.log(typeof { wew: "12321" }); // object
console.log(typeof [1, 2, 3, 4, 5]) //object
大部分都能区分,typeof无法区分出来 null 对象 数组 因为都返回 object
- instanceOf
class abc {}
class exs extends abc{}
var bbb = new exs()
console.log(bbb instanceof abc,'---obj--')
3.Object.prototype.toString.call
0.1+0.2 !=0.3
进制转换 : js做运算会转换成2进制, 但是最高只能存储53位,采用IEEE 754二进制。53位之后的会被截取掉。
call、apply、bind 实现
- call
var obj = {
aaa: '123'
}
function abc() {
console.log(obj.aaa, ...arguments)
}
abc.call(obj,12312);
call做了三件事 ,第一修改abc的执行环境到obj, 第二执行abc函数。返回 abc函数的返回值
Function.prototype.myCall = function (context) {
if (typeof this != 'function') {
throw new Error('不是函数')
}
//不存在为 window对象
context = context ? context : window;
//返回执行结果
var result = null;
//处理参数
var args = [...arguments].slice(1); //还能切数组
context.this = this; //执行方法
result = context.this(...args)
delete context.this;
return result;
}
var obj = {
aaa: '123'
}
function abc() {
console.log(obj.aaa, ...arguments,'这里执行---')
return 2132
}
var res = abc.myCall(obj, 12312,123123);
console.log(res)
结果
- apply
仅需把上述args部分改成 args = [...arguments].slice(1)[0];
- bind
var obj = {
a: "123",
b: 123123
}
Function.prototype.mybind = function (context) {
const fn = this;
if (typeof fn != 'function') {
throw Error('不是函数')
}
var argu = [...arguments].slice(1)
return function Fn() {
return fn.call(this instanceof Fn ? this : context, argu.concat(...arguments))
}
}
var add = function () {
console.log(this.a, this.b);
}
var newo = add.mybind(obj, '12321')
var addNewo = new newo();
js 垃圾回收
- 标记清除
简单来说就是使用的时候,标记好,当不用的时候,就进行清除策略。在js里要实现一个标记器。 缺点: 定时的进行清除。性能不好。
- 引用计数 引用计数就是当var 了一个变量当前标记为0, 当不用了就-1。
强制缓存
强缓存(Cache-Control: max-age=3153600) 协商缓存
浏览器先通过Cache-Control判断是否过期,max-age,no-cache。如果没过期直接用缓存。过期再判断是否有ETag(相当于唯一标识) ,Last-Modified(最后修改时间,只能精确到秒级)。
注意区别,If-Modified-Since是上次服务器返回头部中的Last-Modified信息。
Last-Modified是由服务器发给浏览器的最后修改时间,If-Modified-Since是浏览器发给服务器的最后修改时间。(互相对应)
服务器拿到If-Modified-Since,和自己服务器资源最后修改时间比较,如果一致,那么就返回304,不一致就返回200。
301和302 304 区别
301和302 浏览器拿到这个状态码都会跳转到新的地址url。
301: 代表永久转移,永久重定向。比如当前网站整个迁移,但是当前域名还用,就通过这个进行转移。
302:临时重定向,之前的网站地址还能用,只不过临时重A跳转到B。
最好用301这里有个坑, 302 很容易造成网址劫持。假如我写了一个页面A,我用302重定向到页面B。很可能
因为某种原因,在搜索引擎上会出现页面A的链接,但是点进去又是页面B。
304: 和缓存有关,如果服务器觉得当前浏览器缓存还能用,就会返回304。