1,call和apply区别
定义:
apply调用一个对象的一个方法,用另一个对象替换当前对象。
例如: B.apply(A, agruments) 即A对象应用B对象的方法
call调用一个对象的一个方法,用另一个对象替换当前对象。
例如: B.call(A, arg1, arg2) 即A对象应用B对象的方法
从定义中看出,call和apply都是调用一个对象的一个方法,用另一个对象替换当前对象。不同的是apply只接受两个参数(新对象和数组argumens), call则可以传递多个参数(新对象 + 参数列表)
function Dog(){
this.name = "dog";
this.showName=function(){
console.log("这是一条"+this.name+"!")
}
}
function Cat(){
this.name="cat";
// Dog.apply(this)
this.showName=function(){
console.log(this.name+" eat fish");
}
Dog.apply(this)
};
var cat = new Cat()
// Dog.call(cat) /*call的用法*/
cat.showName() /*这是一条dog*/
console.log(cat.name) /*dog*/
但是如果你apply写的位置不同,结果也将有所变化。如上述代码
如果我将后边的apply注释掉,将上一个apply打开,那么执行showName()得到的结果将是:dog eat fish
2,js 数组或对象浅拷贝深拷贝的几种方法
1,对象浅拷贝
方法一: 对象的合并 Object.assign(),第一个参数必须是个空对象
var obj1 = {a: 1, b: 2}
var obj2 = Object.assign({}, obj1)
obj2 // {a: 1, b: 2}
方法二:对象的解构赋值
var obj1 = {a: 1, b: 2}
var obj2 = {...obj1}
console.log(obj2) // {a: 1, b: 2}
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)
2,对象深拷贝: 通过js的内置对象JSON来进行数组对象的深拷贝 数组、对象深拷贝都可以用这个方法
var obj1 = {a: 1, b: 2}
var obj2 = JSON.parse(JSON.stringify(obj1))
console.log(obj2) // {a: 1, b: 2}
3,数组浅拷贝
方法一:利用数组的 slice 方法或者 concat 方法
var arr1 = [10,20,30,40,50]
var arr2 = arr1.slice(0)
console.log(arr2) // [10,20,30,40,50]
var arr1 = [10,20,30,40,50]
var arr2 = arr1.concat()
console.log(arr2) // [10,20,30,40,50]
4,ajax中get和post区别
- get是把参数拼接到url后边,post是放在请求体中
- get有传参大小限制 Chrome10KB post没有限制
- post相对比get请求安全
- get方式是有缓存的 post没有缓存
GET方式传送数据量小,处理效率高,安全性低,会被缓存,而POST方式传送数据量大,处理效率没有get方式高,数据不会被缓存,对于账号和密码等,比较安全。
5, 检测数据类型的几种方式
1、typeof value
typeof ""; //string
typeof 1; //number
typeof false; //boolean
typeof undefined; //undefined
typeof function(){}; //function
typeof {}; //object
typeof Symbol(); //symbol
typeof []; //object
typeof new Date(); //object
typeof new RegExp(); //object
typeof null // "object" 因为null是一个空对象指针
typeof不能具体的细分对象、数组、正则等,因为不管检测哪一个返回的都是"object"
2、instanceof
instanceof用来判断A是否为B的实例,表达式为:A instanceof B,如果A是B的实例,则返回true,否则返回false。instanceof检测的是原型,内部机制是通过判断对象的原型链中是否有类型的原型。
{} instanceof Object; //true
[] instanceof Array; //true
[] instanceof Object; //true
"123" instanceof String; //false
new String(123) instanceof String; //true
我们可以用下面的代码实现instanceof
function instance(left,right){
let prototype = right.prototype; //获取类型的原型
let proto = left.__proto__; //获取对象的原型
while(true){ //循环判断对象的原型是否等于类型的原型,直到对象原型为null,因为原型链最终为null
if (proto === null || proto === undefined){
return false;
}
if (proto === prototype){
return true;
}
proto = proto.__proto__;
}
}
console.log(instance({},Object)); //true
console.log(instance([],Number)); //false
3、constructor
当一个函数F被定义时,JS引擎会为F添加prototype原型,然后在prototype上添加一个constructor属性,并让其指向F的引用,F利用原型对象的constructor属性引用了自身,当F作为构造函数创建对象时,原型上的constructor属性被遗传到了新创建的对象上,从原型链角度讲,构造函数F就是新对象的类型。这样做的意义是,让对象诞生以后,就具有可追溯的数据类型。
image.png
4、Object.prototype.toString()
toString()是Object的原型方法,调用该方法,默认返回当前对象的[[Class]]。这是一个内部属性,其格式为[object Xxx],其中Xxx就是对象的类型。
对于Object对象,直接调用toString()就能返回[object Object],而对于其他对象,则需要通过call、apply来调用才能返回正确的类型信息
image.png
6, 原型链常见面试题
构造函数:
function Foo(name,age){
this.name=name
this.age=age
this.class='class-1'
}
var f=new Foo('wyr',18)
image.png
构造函数--扩展:
所有的引用类型都是构造函数
var a={} 是 var a=new Object() 的语法糖
var a=[] 是 var a=new Array() 的语法糖
function Foo() 是var Foo=new Function() 的语法糖
使用instanceof 判断一个函数是否是一个变量的构造函数
7,cookie,localStorage,SessionStorage三者的区别
1,生命周期的不同
Cookie 一般由服务器生成,可设置失效时间
localStorage 除非被永久清除,否则永久保存。
sessionStorage 仅在当前会话会有效,关闭页面或浏览器后被清除
2,存储数据的大小
Cookie 一般为4kb
localStorage 和 sessionStorage 一般为5mb
3,与服务器端通信不同
Cookie 每次都会携带HTTP头中,如果使用cookie保存过多数据会带来性能问题
localStorage 和 sessionStorage 仅在客户端(即浏览器)中保存,不参与和服务器的通信
8, v-if v-show区别
v-if 如果值为false 页面不会有html元素生成
v-show 无论值是true还是false 元素都存在页面中 只是display为none 还是占位置的
9, 去除str中所有的空格
function trimAll(str){
var string=''
var arr = []
for(var i=0;i<str.length;i++){
if(str.charCodeAt(i) == 32){ // 空格键盘对应代码32
continue // break用于完全结束一个循环,跳出循环体执行循环后面的语句 可以理解为continue是跳过当次循环中剩下的语句,执行下一次循环。
}else{
arr.push(str[i])
}
}
return string = arr.join('') // join('') 用于把数组中的所有元素放入一个字符串
}
let str = ' Hello world ! '
trimAll(str)
console.log(trimAll(str))
10,JS 面向对象 实现继承的方法
1,原型链继承
核心: 将父类的实例作为子类的原型
缺点: 父类新增原型方法/原型属性,子类都能访问到,父类一变其它的都变了
function Person (name) {
this.name = name
}
Person.prototype.getName = function () { //对原型进行扩展
return this.name
}
function Parent (age) {
this.age = age
}
Parent.prototype = new Person('riemann'); //这一句是关键 //通过构造器函数创建出一个新对象,把老对象的东西都拿过来。
Parent.prototype.getAge = function () {
return this.age;
}
// Parent.prototype.getName = function () { //可以重写从父类继承来的方法,会优先调用自己的。
// console.log(222)
// };
var result = new Parent(22)
console.log(result.getName()); //riemann //调用了从Person原型中继承来的方法(继承到了当前对象的原型中)
11,实现一个深拷贝
深拷贝和浅拷贝是针对复杂数据类型来说的,浅拷贝只拷贝一层,而深拷贝是层层拷贝
let obj={
name:"浩浩",
sex:"男",
ability:["玩游戏"]
}
var obj1 = Object.assign({},obj)
var obj2 = {...obj}
obj.sex="女"
obj.ability.push("看小说")
console.log(obj)
console.log(obj1)
console.log(obj2)
image.png
看出浅拷贝当属性值是基本数据类型时,新的对象和原对象互不影响,但是如果第一层的属性值是复杂数据类型,那么新对象和原对象的属性值其指向的是同一块内存地址
深拷贝实现的目的就是是指新对象和原对象的属性值其指向的不是同一块内存地址:
let obj={
name:"浩浩",
sex:"男",
ability:["玩游戏"]
}
var obj1 = Object.assign({},obj)
var obj2 = {...obj}
var obj3 = JSON.parse(JSON.stringify(obj))
obj.sex="女"
obj.ability.push("看小说")
console.log(obj)
console.log(obj1)
console.log(obj2)
console.log(obj3)
image.png
JSON.parse() 将json字符串转换为json对象
var json = '{"name":"GDT","age":23,"University":"GDUT"}';
console.log(JSON.parse(json)) // {name: "GDT", age: 23, University: "GDUT"}
JSON.stringify()将json对象转换为json字符串
var json = {name:"GDT",age:23,University:"GDUT"}
console.log(JSON.stringify(json)) // '{name: "GDT", age: 23, University: "GDUT"}'
网友评论