js_面向对象_new关键字_对象与this_ES6种对象相关的特性实例

字面量对象

重新介绍 JavaScript(JS 教程) - JavaScript | MDN (mozilla.org)

  • 对象作为函数参数:

在经典的面向对象语言中,对象是指数据和在这些数据上进行的操作的集合。与 C++ 和 Java 不同,JavaScript 是一种基于原型的编程语言,并没有 class 语句,而是把函数用作类。那么让我们来定义一个人名对象,这个对象包括人的姓和名两个域(field)。名字的表示有两种方法:“名 姓(First Last)”或“姓, 名(Last, First)”。使用我们前面讨论过的函数和对象概念,可以像这样完成定义:

function makePerson(first, last) {
return {
first: first,
last: last
};
}
function personFullName(person) {
return person.first + ' ' + person.last;
}
function personFullNameReversed(person) {
return person.last + ', ' + person.first;
}
var s = makePerson('Simon', 'Willison');
personFullName(s); // "Simon Willison"
personFullNameReversed(s); // "Willison, Simon"

利用返回对象的函数创建对象

function makePerson(first, last) {
return {
first: first,
last: last
};
}

利用关键字new调用构造函数(constructor)来得到(或者说constructor修改一个空对象)得到想要的对象

利用原型链修改对象模板中的属性/方法

function Person(first, last) {
this.first = first;
this.last = last;
}
Person.prototype.fullName = function() {
return this.first + ' ' + this.last;
}
Person.prototype.fullNameReversed = function() {
return this.last + ', ' + this.first;
}

原型对象

Person.prototype 是一个可以被 Person的所有实例共享的对象。

它是一个名叫 原型链(prototype chain)的 查询链的一部分:当你试图访问 Person<span>某个实例(例如上个例子中的s)一个没有定义的属性时,解释器会首先检查这个 Person.prototype来判断是否存在这样一个属性。

所以,任何分配给 Person.prototype的东西对通过 this 对象构造的实例都是可用的。

这个特性功能十分强大,JavaScript 允许你在程序中的任何时候修改原型(prototype)中的一些东西,也就是说你可以在运行时(runtime)给已存在的对象添加额外的方法:

s = new Person("Simon", "Willison");
s.firstNameCaps(); // TypeError on line 1: s.firstNameCaps is not a function
Person.prototype.firstNameCaps = function() {
return this.first.toUpperCase()
}
s.firstNameCaps(); // SIMON

new与构造函数(结合this)

实现一个和 new关键字有类似效果的 trivial方法:

  • 下面是一个new 方法的简单实现:
function trivialNew(constructor, ...args) {
var o = {}; // 创建一个对象
constructor.apply(o, args);
return o;
}

note:

这并不是 new 的完整实现,因为它没有创建原型(prototype)链。

(想举例说明 new 的实现有些困难)l因为你不会经常用到这个,但是适当了解一下还是很有用的。

在这一小段代码里,...args(包括省略号)叫作剩余参数(rest arguments)。如名所示,这个东西包含了剩下的参数。

因此,调用

var bill = trivialNew(Person, "William", "Orange");

可认为和调用如下语句是等效的

var bill = new Person("William", "Orange");

this

关键字 this。当使用在函数中时,this 指代当前的对象,也就是 调用了函数的对象

如果在一个对象上使用 点或者方括号来访问属性或方法,这个对象就成了 this。

否则, this 将指向全局对象(global object)。这是一个经常出错的地方。

使用关键字 this 改进已有的 makePerson函数:

function Person(first, last) {
this.first = first;
this.last = last;
this.fullName = function() {
return this.first + ' ' + this.last;
}
this.fullNameReversed = function() {
return this.last + ', ' + this.first;
}
}
var s = new Person("Simon", "Willison");

我们引入了另外一个关键字:new,它和 this 密切相关。

它(new)的作用是创建一个崭新的 空对象{},然后使用指向那个对象的 this调用特定的函数。

注意,含有 this的特定函数不会返回任何值,只会修改 this 对象本身。


new关键字将生成的 this对象返回给调用方,而被 new调用的函数称为构造函数。(是的,只是某个函数被new调用了,那么被调用的函数就叫构造函数;但是一般的,我们会让new调用一个适合用来创建的对象的函数,习惯上,这样的被设计为初始化对象的函数首字母大写,这样用new 调用他们的时候就容易识别了)

指定this(对象)来调用基于该this对象的面向对象的方法

  • 用对象obj.FunctionName()obj[FunctionName]()的行形式调用,方法中的this指的就是obj
  • 用函数对象的apply():
    • FunctionName.apply(thisArg,argArray)
  • 用函数对象的call():
    • FunctionName.call(thisArg,argList)

call()

知道了 newthis的基本特点和工作原理后,我们看一下 call()

function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
console.log(new Food('cheese', 5));//Food { name: 'cheese', price: 5, category: 'food' }
console.log(new Food('cheese', 5).name);// expected output: "cheese"
console.log((new Food('cheese', 5)).name);//the same as `new Food('cheese',5).name`
console.log(Food('cheese', 5));//expected undefined
// console.log(new (Food('cheese',5).name));// Wrong! TypeError
// console.log(Food('Cheese',5).name);//Wrong! TypeError
console.log();

这里,

<strong>call()</strong>方法使用 一个指定的 this 值和 单独给出的一个或多个参数调用一个函数

注意: 该方法的语法和作用与 apply() 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表 ,而 apply() 方法接受的是一个包含多个参数的数组

对于本例代码,的new调用处,创建了一个空对象,然后用该空对象的this去调用函数Food(),Food()将会对这个空对象进行处理,Food()内部调用了Product函数对象的call()方法,该方法将空对象作为this实参,后面的name,price参数列表将传递给Product()函数,这样函数Product所作用于的对象this就是new出来的空对象的this.

new还将生成的this对象返回给调用方(本例的测试中对这个new 所调用的构造函数修饰后的this对象调用(访问)了其name属性.

new 小结

总之,new 是基于新建一个空对象 {}的基础上执行一些操作

apply()

call()中的例子用apply()来改写:

function Food(name, price) {
Product.apply(this, [name, price]);
this.category = 'food';
}

apply()示例 (mozilla.org)

ES6种对象相关的特性

obj = {
d: console.log,
name: "NameInObj",
data: {
name: "nameIndataOfobj",
age: 18
},
methodInObj: function () {
console.log(this.data.name);
console.log(this.data.age);
this.d(this.data);
// console.log(name);
},
/* 定义函数的若干种方式: */
m1: function () {
console.log("I am the method1😎");
},
/* 简化写法m1:将`:function`省略掉 */
m2() {
console.log("I am the method2❤️");
}
,
/* 测试箭头函数的对象绑定特性 */
testThis() {
const that = this;
setTimeout(
function () {
console.log(this.name + " 😎test this within setTimeOut(expected undefined)");
}
);
setTimeout(
function () {
console.log(that.name + " 😎test this within setTimeOut(expected name in obj)");
}
);
setTimeout(() => {
console.log(this.name + ` 👌test that within settimeOut(expected name in obj) `);
}, 0);
}
};
function testmethod() {
obj.methodInObj;
obj.methodInObj();
console.log(obj.methods);
}
// console.log(obj.methods());
// console.log(obj);
function testMn() {
obj.m1();
obj.m2();
}
// testMn()
obj.testThis();
posted @   xuchaoxin1375  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示