JS面试题—原型和原型链
2017-08-08 17:19
309 查看
一、 题目
如何准确判断一个变量是数组类型
写一个原型链继承的例子
描述new一个对象的过程
二、知识点
1.构造函数
特点:默认函数首字母大写,构造函数并没有显示返回任何东西。new 操作符会自动创建给定的类型并返回他们,当调用构造函数时,new会自动创建this对象,且类型就是构造函数类型。
2.构造函数—扩展
var a = {} 其实是 var a = new Object()的语法糖
var a = [] 其实是 var a = new Array()的语法糖
function Foo(){…} 其实是 var Foo = new Function(){…}
使用instanceof判断一个函数是否是构造函数
3.原型规则和示例
原型规则是原型链的基础
所有引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除‘null’以外)
所有引用类型(数组、对象、函数),都具一个_proto_ (隐式原型)属性,属性值是一个普通对象
所有函数,都有一个prototype(显式原型)属性,属性值也是一个普通对象
所有引用类型(数组、对象、函数),_proto_ (隐式原型)属性值指向它的构造函数的prototype(显式原型)属性值
当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的_proto_ (即它的构造函数的prototype)中寻找
tips:循环对象自身的属性时,建议加上hasOwnProperty来保证程序的健壮性
4.原型链
还是采用上面构造函数的例子来解释原型链
5.instanceof
用于判断引用类型属于哪个构造函数的方法
f instanceof Foo的判断逻辑:
f的proto一层一层往上,能否找到Foo.prototype
再试着判断f instanceof Object
三、解答
1.如何准确判断一个变量是数组类型
2.写一个原型链继承的例子
3.描述new一个对象的过程
创建空对象;
var obj = {};
设置新对象的constructor属性为构造函数的名称,设置新对象的_proto_属性指向构造函数的prototype对象;
obj._proto_ = ClassA.prototype;
使用新对象调用函数,函数中的this被指向新实例对象:
ClassA.call(obj); //{}.构造函数();
将初始化完毕的新对象地址,保存到等号左边的变量中
tips:若构造函数中返回this或返回值是基本类型(number、string、boolean、null、undefined)的值,则返回新实例对象;若返回值是引用类型的值,则实际返回值为这个引用类型。
如何准确判断一个变量是数组类型
写一个原型链继承的例子
描述new一个对象的过程
二、知识点
1.构造函数
function Foo(name, age){ this.name = name this.age = age this.class = 'class-1' // return this //默认有这一行 } var f = new Foo('zhangsan', '20') //var f1 = new Foo('lisi', 22) //可创建多个对象
特点:默认函数首字母大写,构造函数并没有显示返回任何东西。new 操作符会自动创建给定的类型并返回他们,当调用构造函数时,new会自动创建this对象,且类型就是构造函数类型。
2.构造函数—扩展
var a = {} 其实是 var a = new Object()的语法糖
var a = [] 其实是 var a = new Array()的语法糖
function Foo(){…} 其实是 var Foo = new Function(){…}
使用instanceof判断一个函数是否是构造函数
3.原型规则和示例
原型规则是原型链的基础
所有引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除‘null’以外)
所有引用类型(数组、对象、函数),都具一个_proto_ (隐式原型)属性,属性值是一个普通对象
所有函数,都有一个prototype(显式原型)属性,属性值也是一个普通对象
所有引用类型(数组、对象、函数),_proto_ (隐式原型)属性值指向它的构造函数的prototype(显式原型)属性值
当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的_proto_ (即它的构造函数的prototype)中寻找
var obj = {}; obj.a = 100; var arr = []; arr.a = 100; function fn(){} fn.a = 100; // 所有引用类型都能拓展属性 console.log(obj.__proto__) console.log(arr.__proto__) console.log(fn.__proto__) //所有引用类型都有_proto_(隐式原型)属性 console.log(fn.prototype) //所有函数,都有一个prototype(显式原型)属性 console.log(obj.__proto__ === Object.prototype)// true 引用类型_proto_(隐式原型)属性值指向它的构造函数的prototype(显式原型)属性值
//当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的*_proto_* (即它的构造函数的prototype)中寻找 //构造函数 function Foo(name, age){ this.name = name; } Foo.prototype.alertName = function(){ alert(this.name) } //创建实例 var f = new Foo('zhangsan'); f.printName = function(){ console.log(this.name); } //测试 f.printName(); //f自身有printName这个属性,所以直接可以调用 f.alertName(); //f自身没有alertName这个属性,所以会去它的_proto_(即它的构造函数的prototype)中寻找
tips:循环对象自身的属性时,建议加上hasOwnProperty来保证程序的健壮性
var item; for(item in f){ //高级浏览器已经在for in 中屏蔽了来自原型的属性 //但是这里建议大家还是加上这个判断,保证程序的健壮性 if(f.hasOwnProperty(item)){ console.log(item) } }
4.原型链
还是采用上面构造函数的例子来解释原型链
//构造函数 function Foo(name, age){ this.name = name; } Foo.prototype.alertName = function(){ alert(this.name) } //创建实例 var f = new Foo('zhangsan'); f.printName = function(){ console.log(this.name); } //测试 f.toString(); //要去f._proto_._proto_中查找 /* f自身没有toString这个属性, 那么f会去它的隐式原型_proto_(即它的构造函数的prototype)中寻找,而f的构 造函数也没有toString这个属性,那该往哪里找? 原型规则中第二、三条提到:所有引用类型(数组、对象、函数),都具一个_proto_(隐式原型)属性,属性值是一个普通对象,意思f._proto_(f.prototype)是个对象 f._proto_是个对象,那么该往f._proto_隐式原型中寻找,即f._proto_._proto_ (f._proto_寻找其对象的构造函数也就是Object) * */
5.instanceof
用于判断引用类型属于哪个构造函数的方法
f instanceof Foo的判断逻辑:
f的proto一层一层往上,能否找到Foo.prototype
再试着判断f instanceof Object
三、解答
1.如何准确判断一个变量是数组类型
var arr = [] arr instanceof Array //true typeof arr // Object typeof是无法判断是否是数组的
2.写一个原型链继承的例子
//写一个封装DOM的例子 function Elem(id){ this.elem = document.getElementById(id); } Elem.prototype.html = function (val) { var elem = this.elem; if(val){ elem.innerHTML = val; return this; //链式操作, 可有可无 }else{ return elem.innerHTML; } } Elem.prototype.on = function(type, fn){ var elem = this.elem; elem.addEventListener(type, fn); return this; } var div1 = new Elem('div1'); //console.log(div1.html()) div1.html('<p>hello world<p>').on('click', function(){ alert('clicked'); }).html('<p>javascript<p>')
3.描述new一个对象的过程
创建空对象;
var obj = {};
设置新对象的constructor属性为构造函数的名称,设置新对象的_proto_属性指向构造函数的prototype对象;
obj._proto_ = ClassA.prototype;
使用新对象调用函数,函数中的this被指向新实例对象:
ClassA.call(obj); //{}.构造函数();
将初始化完毕的新对象地址,保存到等号左边的变量中
tips:若构造函数中返回this或返回值是基本类型(number、string、boolean、null、undefined)的值,则返回新实例对象;若返回值是引用类型的值,则实际返回值为这个引用类型。
相关文章推荐