js的作用域和作用域链
- 作用域就是变量或者函数有权访问的数据的范围,每个作用域都关联一个变量对象,环境中的变量和函数都保存在这个对象中。
- 每个函数都有自己的作用域,执行一个函数时,函数的作用域就会被进入作用域栈中,函数执行完后,自己的作用域出栈,控制权给之前的函数作用域。
- 作用域链用于保证对作用域可访问数据的有序访问。作用域链的第一个对象是当前的作用域,然后下一个是包含的作用域,直到全局变量作用域。访问数据会按照作用域链访问,相同的变量,前面会将后面屏蔽掉。
js的原型和原型链
-
我们创建的每一个函数都有一个prototype属性,这个属性是个指针,指向函数的原型,函数所有实例共享原型包含的属性和方法,每个原型对象也都有一个constructor属性指向所对应的函数。
-
每个构造函数的实例都有一个属性[[prototype]](谷歌,火狐里是_proto_)指向构造函数的原型对象。
-
代码读取实例属性时会先搜索实例本身,在搜索原型对象上的属性,相同属性实例会把原型屏蔽掉。无法通过实例更改原型的属性。
- 如果我们让B原型对象等于A构造函数的实例,此时B原型对象作为A的实例,将获得指向A原型对象的指针,因此获得A原型对象上的属性和方法,B的实例也将获得A和B原型对象上的方法,如此实现了B继承A的原型对象。如此往下循环,一个实例与原型构成的链条就是原型链。(B的原型对象也获得了A构造函数的属性和方法)
js的继承
原型链
可以通过原型链实现继承
缺点:1.从A的原型对象继承的方法,都成为了B的原型对象的属性,因而B的实例全部共享这些属性
2.创建B的实例时,无法向A构造函数传递参数(传了会影响其他实例)
借用构造函数
示例
function A(name){
this.name = name;
}
function B(){
A.call(this,"yangyang");
}
借用call和apply可以在B中定义新的A函数中的初始化对象,如此B的实例将会获得A的构造函数中的对象,且各个实例彼此独立。
优点:
1.实例中继承的对象和方法不在共享
2.可以传参数
缺点:
1.无法实现函数复用,此方法继承的方法是独立的
组合继承
就是将前两种方法结合起来,继承对象用借用构造函数,继承方法依然用原型链。
(在原型链中存在的问题理论上依然存在,即B的原型对象是A的实例,则B的原型上有A的构造函数中的对象,它们仍然是B实例共享的,但因为在B的构造函数中,将A的初始化对象有定义了一遍,因而屏蔽掉了B原型对象中的这些属性)
(思考:是否有必要将B原型的consructur指向B构造函数,为什么)
js的dom元素操作
基本dom操作
获取样式用getComputedStyle(元素).样式属性。
ajax请求详细怎么实现,和其中的响应状态
菜鸟教程
先建一个实例var xml=new xmlrehttpquest()
在设置方法和url xml.open(“GET”,“url”);(最后一个参数表示是否异步,默认为true)
然后发送请求 xml.send(null);(没有参数时要写入null,get方法没有参数,post请求则填入数据)
如果是post请求 需要设置请求头
xmlHttp.setRequestHeader(“Content-Type”,“application/x-www-form-urlencoded”);
js的基础类型和引用类型
apply,bind和call
js中new和object.creat区别
个人测试
var a = new A()
对象a会获得函数A的原型对象上的方法和属性,也会继承函数A构造函数中的属性。
var a = Object.create(A.prototype);
对象a只会获得函数A的原型对象上的方法和属性。
在mdn文档里
通过object.create()的这个用法可以实现继承
// Shape - 父类(superclass)
function Shape() {
this.x = 0;
this.y = 0;
}
// Rectangle - 子类(subclass)
function Rectangle() {
Shape.call(this); // call super constructor.
}
// 子类续承父类
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
这样,子类的原型对象就只获得了父类的原型方法,而没有顺带把父类构造函数中的方法拿走。
事件委托、事件冒泡、事件捕获
js BOM
浏览器如何渲染
js跨域实现
请求get和post的区别
argument
JavaScript 之arguments、caller 和 callee 介绍
深拷贝与浅拷贝
Object.assign({}, obj);浅复制,因为 Object.assign()拷贝的是属性值。假如源对象的属性值是一个对象的引用,那么它也只指向那个引用。
深拷贝与浅拷贝
序列化与反序列化
序列化
- JSON.stringify();能生成js对象的JSON对象,js对象的所有函数及原型都将被忽略,值为undefined的属性也将被跳过。
- 除了要序列化的对象外,还接受两个参数。
- 第二参数个可以是函数,也可以是数组,是数组时就只序列化数组中的属性,是函数时函数有两个参数,即对象每个属性的键值对,根据返回的值决定序列化后属性的值,返回undefined就忽略掉属性。
- 第三个参数决定结果的缩进,若为数值则代表每一级别开头缩进空格数,最大为10,若为字符串则代表每一级别开头的缩进字符,最大长度为10.
- 可以给每个对象定义一个toJSON方法,返回自身的JSON格式,序列化时将首先调用这个方法,(Date本身就有一个,会转换为日期字符串)
序列化js对象顺序如下:
1.存在toJSON方法,则调用,否则返回本身
2.如果有第二个参数,则根据参数过滤对象属性。
3.对结果进行序列化。
4.如果有第三个参数,进行格式化。
反序列化
- JSON.parse可以将JSON对象转化为js对象,还接受一个参数,该参数是一个函数,同样用于过滤属性,参数为属性键值对,反序列化的属性的值将为返回值,返回undefined将会删除属性。
闭包
cookie session 和localstorage
两种盒模型
修改元素class
用classlist,add和remove可以添加或者删除多个类名