2020面经-JS部分(call,new,原型,继承,创建对象,js三大事件)

JS继承的方法及优缺点原生js继承怎么实现原型链继承function Parent() { this.name = 'parent'}Parent.prototype.sayName = function() { alert(this.name)}function Child() { this.age = 20;}Child.prototype = new Parent(); // 改造子类构造函数的原型,使其指向父类的实例。let child = new Ch
摘要由CSDN通过智能技术生成

1、call,apply和bind

相同点:
都可以把一个函数应用到其他对象上;
都是用来改变函数的this对象的指向的;
第一个参数都是this要指向的对象;
都可以利用后续参数传参。

不同点:
call,apply是修改函数的作用域,即修改this指向,并且立即执行,
而bind是返回了一个新的函数,不是立即执行;

而call和apply的区别是call接受逗号分隔的无限多个参数列表,apply则是接受数组作为参数。

var xw = {
   
    name: "小王",
    gender: "男",
    age: 24,
    say: function() {
   
        console.log(this.name + " , " + this.gender + " ,今年" + this.age);
    }
}
var xh = {
   
    name: "小红",
    gender: "女",
    age: 18
}
xw.say();//小王 , 男 ,今年24
xw.say.call(xh)//小红 , 女 ,今年18
xw.say.apply(xh)//小红 , 女 ,今年18
xw.say.bind(xh)()//小红 , 女 ,今年18

在这里插入图片描述
接受参数:

var a = {
   
    name: "小王",
    gender: "男",
    age: 24,
    say: function(school, grade) {
   
        console.log(this.name + " , " + this.gender + " ,今年" + this.age + " ,在" + school + "上" + grade);
    }
}
var b = {
   
    name: "小红",
    gender: "女",
    age: 18
}
a.say.call(b, "实验小学", "六年级");
a.say.apply(b, ['第一中学', '初一'])
    // bind返回一个函数,调用的时候传参
a.say.bind(b, "高级中学", "高三")();

在这里插入图片描述


2、new一个对象发生了什么

• 创建一个空对象,将它的引用赋给 this,继承函数的原型。
• 通过 this 将属性和方法添加至这个对象
• 最后返回 this 指向的新对象,也就是实例(如果没有手动返回其他的对象)

重学前端专栏中,看到了比较符合我心意的,同时也是符合原理的描述:

• 以构造器的prototype属性为原型,创建新对象;
• 将this(也就是上一句中的新对象)和调用参数传给构造器,执行;
• 如果构造器没有手动返回对象,则返回第一步创建的新对象,如果有,则舍弃掉第一步创建的新对象,返回手动return的对象。
在这里插入图片描述

new过程中会新建对象,此对象会继承构造器的原型与原型上的属性,最后它会被作为实例返回这样一个过程。知道了原理,我们来手动实现一个简单的new方法。

// 构造器函数
let Parent = function (name, age) {
   
    this.name = name;
    this.age = age;
};
Parent.prototype.sayName = function () {
   
    console.log(this.name);
};
//自己定义的new方法
let newMethod = function (Parent, ...rest) {
   
    // 1.以构造器的prototype属性为原型,创建新对象;
    let child = Object.create(Parent.prototype);
    // 2.将this和调用参数传给构造器执行
    let result = Parent.apply(child, rest);
    // 3.如果构造器没有手动返回对象,则返回第一步的对象
    return typeof result  === 'object' ? result : child;
};
//创建实例,将构造函数Parent与形参作为参数传入
const child = newMethod(Parent, 'echo', 26);
child.sayName() //'echo';

//最后检验,与使用new的效果相同
child instanceof Parent//true
child.hasOwnProperty('name')//true
child.hasOwnProperty('age')//true
child.hasOwnProperty('sayName')//false

扩展:形参。。。
https://www.cnblogs.com/echolun/p/10668186.html


3、原型原型链

构造函数上的方法

  1. 在构造函数上直接定义方法(不共享)
function Person() {
   
    this.say = function () {
   
        console.log('hello');
    }
}
let p1 = new Person();
let p2 = new Person();
p1.say(); // hello
p2.say(); // hello
console.log(p1.say === p2.say); // false

很明显,p1 和 p2 指向的不是一个地方。 所以 在构造函数上通过this来添加方法的方式来生成实例,每次生成实例,都是新开辟一个内存空间存方法。这样会导致内存的极大浪费,从而影响性能。
.

  1. 通过原型添加方法(共享)
    构造函数通过原型分配的函数,是所有对象共享的。
function Person(name) {
   
    this.name = name;
}
Person.prototype.say = function () {
   
    console.log('hello ' + this.name);
}
let p1 = new Person('张三');
let p2 = new Person('李四');
p1.say(); // hello 张三
p2.say(); // hello 李四
console.log(p1.say === p2.say); // true

所以我们经常 将公共属性定义到构造函数里,将公共方法放到原型对象上

要点

1、所有的引用类型(数组、函数、对象)可以自由扩展属性(除null以外)。

2、所有的引用类型都有一个’_ _ proto_ _'属性(也叫隐式原型,它是一个普通的对象)。

3、所有的函数都有一个’prototype’属性(这也叫显式原型,它也是一个普通的对象)。

4、所有引用类型,它的’_ _ proto_ _’属性指向它的构造函数的’prototype’属性。

5、当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它的’_ _ proto_ _'属性(也就是它的构造函数的’prototype’属性)中去寻找。
【当对象属性不存在就会去他隐原型找,但是隐原型指向了构造函数的显示原型,所以去构造函数的显式原型中找】

原文地址

原型

先来看一个原型的例子。

		//这是一个构造函数
		function Foo(name,age){
   
			this.name=name;
			this.age=age;
		}
		/*根据要点3,所有的函数都有一个prototype属性,这个属性是一个对象
		再根据要点1,所有的对象可以自由扩展属性
		于是就有了以下写法*/
		Foo.prototype={
   
			// prototype对象里面又有其他的属性
			showName:function(){
   
				console.log("I'm "+this.name);//this是什么要看执行的时候谁调用了这个函数
			},
			showAge:function(){
   
				console.log("And I'm "+this.age);//this是什么要看执行的时候谁调用了这个函数
			}
		}
		var fn=new Foo('小明',19)
		/*当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它
		构造函数的'prototype'属性中去找*/
		fn.showName(); //I'm 小明
		fn.showAge(); //And I'm 19

这就是原型,很好理解。那为什么要使用原型呢?

试想如果我们要通过Foo()来创建很多很多个对象,如果我们是这样子写的话:

	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《java面经-百度准入职老哥整理.pdf》是一份关于百度准入职面试的Java面经整理。这份面经是由百度准入职的老哥整理而成,其中记录了一些面试时可能会遇到的问题以及解答方法。 这份面经对于准备参加百度准入职面试的人来说非常有价值。首先,它列出了一些常见的面试问题,涵盖了Java语言的各个方面,包括基础知识、数据结构与算法、设计模式、多线程、网络编程等等。通过仔细研究和复习这些问题的答案,可以帮助面试者全面了解Java语言的特性和应用。 其次,这份面经还提供了问题的解答思路和方法,帮助面试者理清思路,正确回答问题。这对于很多面试者来说特别有帮助,因为在面试时有时会遇到一些棘手的问题,有了这份面经的指导,面试者可以更好地掌握应对策略。 不过需要注意的是,面经作为一份参考资料,不能完全依赖于它来准备面试。面试官可能会问一些不在面经中列出的问题,因此考生还是需要自己对Java语言有充分的了解,并能够熟练运用。同时,面试官还会关注考生的沟通能力、解决问题的能力以及对新技术的学习和掌握能力。 总体来说,《java面经-百度准入职老哥整理.pdf》是一份非常宝贵的资料,可以帮助面试者对Java面试中可能会遇到的问题有更深入的了解,提供了解答思路和方法。但记住,面试准备还需要多方面的知识积累和实践经验的积累,才能在面试中展现自己的优势。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值