【JS小知识】this的指向、工厂方法、构造函数及优化、prototype原型、forEach()的使用

/**
 * 解析器在调用函数时,每次都会向函数内部传递一个隐含的参数
 *     这个隐含的参数就是this,this指向的是一个对象,
 *     这个对象我们称为函数执行的上下文对象,
 *     根据函数的调用方式的不同,this会指向不同的对象
 *         1、以函数方式调用,this是window
 *         2、以方法的形式调用时,this就是调用方法的那个对象
 *         3、以构造函数的形式调用时,this是新创建的对象
 * */

function func(){
	console.log(this.name);
}

// 创建一个对象
var obj = {
	name:"sun",
	sayName:func
};

var obj2 = {
	name:"zhu",
	sayName:func
};

var name = "全局的name属性";
//以函数方式调用,this是window
func(); 
//以方法的形式调用,this是调用方法的对象
obj.sayName();
obj2.sayName();

 /**

 * 由于普通创建多个对象时会占用大量篇幅,而此类代码吗是可以复用的,因此
 * 使用工厂方法创建对象
 *         通过该方法可以大批量的创建对象
 *         使用工厂方法创建的对象,使用的构造函数都是Object
 *         所以创造的对象都是objec类型
 *         就导致我们无法区分出多种不同类型的对象    
 * */

普通创建与工厂方法创建对象对比如下所示:

// 普通创建对象
var obj01 = {
	name:"sun",
	age:28,
	gender:"男",
	sayName:function(){
		console.log(this.name);
	}
}

var obj02 = {
	name:"zhu",
	age:218,
	gender:"男",
	sayName:function(){
		console.log(this.name);
	}
}
var obj03 = {
	name:"sha",
	age:286,
	gender:"nv",
	sayName:function(){
		console.log(this.name);
	}
}

obj03.sayName();
// 使用工厂方法创建对象
function createPerson(name, age, gender){
	// 创建一个新的对象
	var obj = new Object();
	
	// 向对象中添加属性
	obj.name = name;
	obj.age = age;
	obj.gender = gender;
	obj.sayName = function(){
		console.log(this.name);
	}
	
	return obj;
}

var sun = createPerson("sun", 28, "男");
var zhu = createPerson("猪", 28, "男");
var bai = createPerson("白", 228, "女");

bai.sayName();

/**
 * 由于工厂方法每次都要创建一个新的对象,所以我们使用构造函数
 * 构造函数
 * 创建一个构造函数,专门用来创建Person对象的
 *         构造函数就是一个普通的函数,创建方式和普通函数没有区别,
 *         不用的是构造函数习惯上首字母大写
 * 
 * 构造函数和普通函数的区别就是调用方式的不同
 *        普通函数是直接调用,而构造函数需要使用new关键字来调用 
 *
 * */

代码如下所示(分为加入形参与不加形参两种):

function Person(){
	this.name = "hanzi";
	this.age = 18;
	this.sayName = function(){
		console.log(this.name);
	}
}

// 加入形参以能复用构造函数
function Person_New(name, age){
	this.name = name;
	this.age = age;
	this.sayName = function(){
		console.log(this.name);
	}
}

var per = new Person();
var per1 = new Person_New("卓", 888);
var per2 = new Person_New("卓", 888);

per.sayName();
per1.sayName();
per2.sayName();

// 使用instanceof 可以检查一个对象是否是一个类的实例
// 语法:对象instanceof 构造函数,如果是,则返回true,否则返回false
console.log(per instanceof Person);
// 判断两个对象调用的方法是否一致,此处返回值应为false,因为每次调用方法都是创建新的对象
// 想要解决这种问题就要优化构造函数
console.log(per1.sayName == per2.sayName);

/**
 * 优化构造函数
 * 将function写到构造函数的属性中的时候,构造函数执行一次就会创建一个方法
 *         执行1000次就会创建1000次的方法,但其作用是一样的,
 *         因此,我们将它写到全局中
 * 
 * 但是!!!!将函数定义在全局作用域,污染了全局作用域的命名空间
 * 而且定义在全局作用域中也很不安全,所以使用prototype(原型)
 * 将函数写到构造函数的原型中,可以让所有对象访问到它
 * */

function Person_New02(name, age){
	this.name = name;
	this.age = age;
	this.sayName = fun;
}

function fun(){
	console.log(this.name);
}

var per3 = new Person_New02("卓11", 888);
var per4 = new Person_New02("卓11", 888);

per3.sayName();
per4.sayName();
console.log(per3.sayName == per4.sayName);

/**
 * prototype原型
 * 我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype
 *         这个属性对应着一个对象,这个对象就是我们所谓的原型对象
 * 如果函数作为普通函数调用prototype没有任何作用
 * 当函数通过以构造函数调用时, 他所创建的对象中都会有一个隐含的属性指向该构造函数的原型对象
 * 我们可以通过__proto__来访问属性
 * 原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象
 *         我们可以将对象中共有的内容,统一设置到原型对象中
 * 
 * 当我们访问对象的一个属性或者方法时,它会先在对象自身中寻找,如果有则直接使用
 *         如果没有则在对象的原型对象中寻找,如果有则直接使用
 *         一直找到Object对象,若没有则返回Undefined
 *     
 * 以后我们创建构造函数时,可以将这些对象共有的属性和方法,同一添加到构造函数的原型对象中,
 *         这样不用分别为每一个对象添加,也不会影响到全局作用域就可以使每个对象都具有这些属性和方法了
 * 
 * */
 

function MyClass(){
	
}

// 向MyClass的原型中添加属性a
MyClass.prototype.a = 123;

var myc = new MyClass();

console.log(myc.__proto__ == MyClass.prototype);
console.log(myc.a);

// 向myc中添加a属性
myc.name = "我是myc中的name";
console.log(myc.name);

//向MyClass的原型中添加方法
MyClass.prototype.sayHello = function(){
	console.log("我是原型中的方法 ");
}
myc.sayHello();

// 可以使用hasOwnProperty()来检查自身中是否含有该函数
console.log(myc.hasOwnProperty("name"));

/**
 * forEach()方法需要一个函数作为参数
 *         像这种函数,由我们创建但不由我们调用,我们称为回调函数
 * 
 * */

//创建一个数组
var arr = ["孙悟空","猪八戒","白骨精","牛魔王"];

arr.forEach(function(value, index, obj){
	console.log(value);
});

 

 

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 JavaScript 中,数组的原型对象是 Array.prototype,我们可以通过给 Array.prototype 添加方法来实现对数组的扩展。下面是使用原型封装 forEach 函数的代码: ```javascript Array.prototype.myForEach = function(callback) { for (let i = 0; i < this.length; i++) { callback(this[i], i, this); } } ``` 这个方法接收一个回调函数作为参数,然后遍历数组,对每个元素执行回调函数。回调函数接收三个参数:当前元素、当前索引和整个数组。 使用时,可以像使用原生的 forEach 方法一样使用方法: ```javascript const arr = [1, 2, 3]; arr.myForEach((item, index, array) => { console.log(item, index, array); }); ``` 输出: ``` 1 0 [1, 2, 3] 2 1 [1, 2, 3] 3 2 [1, 2, 3] ``` ### 回答2: 在JavaScript中,可以使用原型封装来自定义forEach函数。原型JavaScript中对象的一个属性,它可以包含共享的方法属性,被所有该对象的实例所共享。 要封装forEach函数,我们可以将其作为一个新的方法添加到数组的原型中。这样,在所有数组实例中都可以使用这个自定义的forEach函数。 下面是一个示例代码: ```javascript Array.prototype.myForEach = function(callback) { for (let i = 0; i < this.length; i++) { callback(this[i], i, this); } }; // 使用自定义的forEach函数 const numbers = [1, 2, 3, 4, 5]; numbers.myForEach(function(number, index, array) { console.log(number, index, array); }); ``` 在上面的示例中,我们通过在Array的原型上创建一个新的方法"myForEach"来封装forEach函数。该方法使用了一个回调函数作为参数,然后在数组的每个元素上调用该回调函数,并传入当前元素值、索引和数组本身作为参数。 可以看到,在使用自定义的forEach函数时,可以像使用原生的forEach一样,传入一个回调函数作为参数,然后在回调函数中处理数组的每个元素。 通过使用原型封装,我们可以在JavaScript中自定义函数,并将其添加到预定义的对象中,使其在所有实例中可用。这种方法使得我们可以更灵活地扩展JavaScript的内置功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值