JavaScript第三篇
一些常见的面试题内容,希望也能助你一臂之力🌸🌸🌸🌸🌸
Q1、什么是对象?
JavaScript 中的所有事物都是对象:字符串、数值、数组、函数...
此外,JavaScript 允许自定义对象。
通俗的可以理解为:(1)多个数据的封装体;(2)用来保存多个数据的容器;(3)一个对象代表现实中的一个事物
Q2、对象的作用及其组成?
作用:统一管理多个数据
组成:属性 :属性名(str):属性值(任意数据类型)
方法: 属性名(str):属性值(function)
如何获取对象的属性或者方法?
一般情况:对象.属性名
特殊类型:对象['属性名']
//1、属性名包含特殊字符'-'
//2、变量名不确定
//举个例子
// 创建对象p
var p = {
name:'小王',
sayHello:function(){
console.log(hello);
}
};
console.log(p.name); //通过属性名获取属性值
console.log(p.sayHello); //通过属性名获取方法
//特殊情况
//创建对象P
var P = {};
// p.content-type = 'text/json'; //属性名字错误
P['content-type'] = 'text/json'; //向对象身上添加属性
console.log(P['content-type']);//通过属性名获取属性值
var proName = 'myAge'; //变量名不确定
var value = 18;
P[proName] = value; // p.proName = value; //不能使用myAge作为属性名
console.log(P) //{myAge:18}
Q3、对象的类型有哪些?
1、内建对象:由ESB标准中定义的对象,object function
2、宿主对象:由js运行环境提供的对象
3、自定义对象:由开发人员创建
Q4、自定义对象创建的方式有哪些?
1、object构造函数创建对象(起始时不确定对象的属性)
var p = new Object; || var obj = {};
p.name = 'Tom'
2、字面量创建对象,同时指定属性和方法。(可以创建多个对象,但是代码冗余)
var p = {
name:'Tom',
steAge:function(){}
}
3、工厂模式,返回一个对象的函数(对象没有一个具体的类型)
function createPerson(name){
var obj = {
name:'tom'
}
return obj;
}
var c1 = createPerson('Tom');//创建一个新对象
var c2 = createPerson('Jerry');//创建一个新对象
4、自定义构造函数(对象身上存在相同的方法,可以将其放在原型上)
function Person(name,age){
this.name = name;
this.age = age;
}
var p1 = new Person('Tom',13);
var p2 = new Person('XiaoTian',15);
//构造函数
与一般函数区别:
1、普通函数是直接调用 Person();
2、构造函数需要使用new关键字调用 new Person();
执行流程:
1、立刻创建一个新的对象
2、将新建的对象设置为函数中的this
3、逐行执行代码
4、将对象作为返回值
特点:
使用同一个构造函数创建的对象,称为一类对象,构造函数称为一个类
实例:
通过该构造函数创建的对象,称为该类的实例(比如上述的p1、p2)
5、构造函数+原型的组合模式
function Person(name,age){
this.name = name; //在构造函数中只初始化一般函数
this.age = age;
}
Person.prototype.setAge = function(age){ //往原型身上添加方法
this.age = age;
}
var p1 = new Person('Tom',12);
var p2 = new Person('Jack',13);
console.log(p1,p2)
Q5、什么是原型、什么是原型对象、什么是原型链?
原型:
原型也是个对象。可以通俗的认为它是个函数
原型对象:
新创建的每个函数都有一个prototype属性,它默认指向一个object空对象(即为原型对象)
原型对象中有一个属性constructor,它指向函数对象
显示原型与隐式原型
每个函数Person都有一个prototype,即显示原型。在定义函数时自动添加的,默认是一个空的object。
function Person(){}; console.log(Person.prototype)
每个实例对象都有一个__proto__,即隐式原型。创建对象时自动添加的,默认值为构造函数的prototype的属性值
var p = new Person();console.log(p.__proto__); || this.__proto__
对象的隐式原型的值 为 其对应构造函数 的显示原型的值
console.log(fun.prototype == fu.__proto__)
原型链
访问一个对象的属性时,先在自身属性上找,找到返回
没有则去原型对象中寻找,
如果原型中没有则去原型的原型中寻找,直到Object对象的原型
举个例子,原型链
//举个代码例子
function Fnc(){
// console.log(this); // Fnc {};使用new 关键字,this指向Fnc
this.run = '2'; //step2、对象自身没有,向构造函数中找
}
var obj = new Fnc(); //obj对象
obj.run = '1'; //step1、对象自身找
// 这里将step4写到3之前是为了测试查找顺序,写到之后会覆盖。
// 会对它的查找顺序出现理解错误
Fnc.prototype.run = '4'; //step4、构造函数的原型
obj.__proto__.run = '3'; // step3、构造函数中没有,向对象的原型中查找
Object.prototype.run = '5';//step5、当前原型的原型
console.log(obj.run);
// 可以按照 1 2 3 4 5顺序去注释,看obj.run打印的结果
Q6、变量提升与函数提升?
//变量提升与函数提升
变量声明提升:
通过var定义(声明)的变量,在定义语句之前就可以访问到
值:undefined
函数声明提升:
通过function声明的函数,在之前就可以直接调用
值:函数定义(对象)
函数必须是声明的方式
fun();
function fun(){};
var a = function fun(){};//函数表达式
先执行变量提升,再执行函数提升
Q7、什么是上下文?
函数代码的分类:
全局代码、局部代码(函数)
(1)全局执行上下文
在执行全局代码之前将window确定为全局执行上下文
对全局数据进行预处理(搜集数据)
var 定义的全局变量----undefined,添加为winddow的属性
function声明的全局函数----赋值,添加为window的方法
this-----赋值(window)
开始执行全局代码
(2)函数执行上下文
在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象。(虚拟的,存在于栈中)
在局部数据进行预处理
形参变量---赋值(在实参赋值),添加为执行上下文的属性
arguments--赋值(实参列表),添加为执行上下文的属性
var定义的局部变量---undefined,添加为执行上下文的属性
function声明的函数--赋值(fun),添加为执行上下文的属性
this---赋值(调用函数的对象)
开始执行函数体代码
执行上下文栈
在全局代码执行前,JS引擎会创建一个栈来存储管理所有的执行上下文对象
在全局执行上下文(window)确定后,将其添加到栈中
在函数执行上下文创建后,将其添加到栈中
在当前函数执行完后,将栈顶的对象移除
当所有的代码执行完后,栈中只剩下window
Q8、继承的方式有哪些?
// 1、原型链继承(让子类型的原型 为 父类型 的一个实例对象)
// 1、父类型
function Supper(){
this.supProp = 'Super proerty'
}
// 2、父类型添加方法
Supper.prototype.showSupperProp = function(){
console.log(this.subProp)
}
// 4、子类型的原型 为 父类型的一个实例对象
Sub.prototype = new Supper(); //导致Sub的constructor:ƒ Supper()
// 5、让子类型的constructor指向子类型(修改指向)
Sub.prototype.constructor = Sub; //constructor:ƒ Sub()
// 3、子类型
function Sub(){
this.subProp = 'Sub proprty'
}
// 7、子类型添加方法
Sub.prototype.showSubProp = function(){
console.log(this.subProp)
}
// 8、创建子类型的实例对象
var sub = new Sub();
// 9、子类型的实例对象可以调用父类型的方法
sub.showSupperProp(); //子类能继承父类型的方法
console.log(sub)
// 2、借用构造函数继承(其实没有继承关系,虚晃^_^)
//构造函数继承
// 父类型
function Person(name,age){
this.name = name,
this.age = age
}
// 子类型
function Student(name,age,price){
// 在子类型的构造函数 中通用call() 调用父类型构造函数
Person.call(this,name,age); //this.Person(name,age)
/*
this.name = name,
this.age = age
*/
this.price = price
}
var s = new Student('tom',20,1);
console.log(s)
// 3、组合继承(原型链+构造函数组合)
// 父类型
function Person(name,age){
this.name = name,
this.age = age
}
Person.prototype.setName = function(name){
this.name = name
}
// 子类型
function Student(name,age,price){
// 在子类型的构造函数 中通用call() 调用父类型构造函数
Person.call(this,name,age); // 为了得到属性
this.price = price
}
Student.prototype = new Person();//为了看到父类型的方法
Student.prototype.constructor = Student();//修正constructor
Student.prototype.setPrice = function(price){
this.price = price
}
// 4、ES6中可是使用constructor 和extends 关键字
class Parent{
constructor(){
this.age = 18
}
}
class Child extends Parent{
constructor(){
super();
this.name = '张三'
}
}
let c = new Child();
console.log(c,c.name,c.age);//Child {age: 18, name: '张三'} '张三' 18
休息一下,下一篇下一篇