Js定义方法


文章1

参考链接:JS 定义方法的三种方式_形形色色的人的博客-CSDN博客_js定义方法

JS定义方法的三种方式

JS函数调用的四种方法:方法调用模式,函数调用模式,构造器调用模式,apply,call调用模式

1.方法调用模式:

先定义一个对象,然后在对象的属性中定义方法,通过myobject.property来执行方法,this即指当前的myobject 
对象。
var blogInfo={
  blogId:123,
  blogName:"werwr",
  showBlog:function(){alert(this.blogId);}
};
blogInfo.showBlog();

 

2.函数调用模式

定义一个函数,设置一个变量名保存函数,这时this指向到window对象。

在函数中和函数外分别用var定义一个变量a,函数外的变量a是全局变量,函数内的变量a是局部变量

在一个js脚本中全局变量隶属于window对象,即window.myfunc(3,4)也可调用。

var myfunc = function(a,b){
  return a+b;
}
alert(myfunc(3,4));

window.document.getElemnetById("header");

document.getElemnetById("header")

3.构造器调用模式

定义一个函数对象,在对象中定义属性,在其原型对象中定义方法。
在使用prototype的方法时,必须实例化该对象才能调用其方法。
var myfunc = function(a){
  this.a= a;
};
myfunc.prototype = {
  show:function(){alert(this.a);}
}
var newfunc = new myfunc("123123123");
newfunc.show();

4.apply,call调用模式

var myobject={};
var sum = function(a,b){
  returna+b;
};
var sum2 = sum.call(myobject,10,30);
//var sum2 =sum.apply(myobject,[10,30]); 
alert(sum2);
 


文章2

JavaScript中定义函数的三种方法 - html中文网参考链接:JavaScript中定义函数的三种方法 - html中文网

/*第一种方法,使用function语句,格式如下*/

function fn(){
  alert("这是使用function语句进行函数定义");
}
fn();

/*第二种方法,使用Function()构造函数克隆函数*/ 

var F = new Function("a","b","alert(a+b)");
F(a,b);

其实相当于如下代码:
function F(a,b){
  alert(a+b);
}

/*第三种方法,使用函数直接量*/

var zhenn = function(){
  alert("zhenn");
}
zhenn();


文章3

参考链接:JavaScript自定义函数(函数的定义、调用、参数、返回值)

JavaScript自定义函数(函数的定义、调用、参数、返回值)

 语法:

function 函数名 ( 形式参数 1, 形式参数 2,…, 形式参数 n){

         语句

         return 返回值 ;//也可以没有返回值

}

  • 使用function关键字。而function关键字后面是函数名,与其他的语言不同的是,JavaScript中的函数不需要说明返回值的类型。
  • 函数的命名规则与其变量名的命名规则相同,(详细请点击:JavaScript的核心语法之变量
  • 函数名后的 () 可以包含若干个参数,也可以选择不带任何参数。
  • 最后是一对 {}中,包含着具体实现程序的某些特定功能的若干语句或脚本代码
  • JavaScript中函数参数的特殊性:

     · 在JavaScript中函数声明了参数,在调用时可以不传递参数,但这在其他编程语言中是会出现编译错误的。

     ·不管函数在声明时有多少个参数,但调用函数时可以传递若干个参数值给函数,并且实际传递的参数值还可以在函数内部进行获取

    在函数被调用时,一个 arguments 对象就会被创建,它只能使用在函数体中,以数组的形式来管理函数的实际参数

 例:(用函数计算班级学生的人数和期中考试的班级平均分)for循环的详细讲解:JavaScript流程控制语句——循环结构

<body>
    <script type="text/javascript">
        function getTotal() {
            var count; //班级人数
            var sum = 0; //班级总平均分
            count = arguments.length; //获取count数组的长度,在后期我们进行学习
            for (var i = 0; i < count; i++) {
                sum += arguments[i]; //依次获取count数组中的学生的成绩,并进行相加
            }
            sum = sum / count; //计算班级总平均分
            document.write("班级的总人数是:" + count + "人,班级期中考试的总平均分为:" + sum);
        }
    </script>
    <h3>
        三班:
        <script type="text/javascript">
            getTotal(85, 95, 98, 89, 90, 80); //调用getTotal
        </script>
        <br/> 
        四班:
        <script type="text/javascript">
            getTotal(80, 85, 90, 75, 65, 70, 70, 60); //调用getTotal
        </script>
    </h3>
</body>


文章四

参考链接:js中定义函数的3种方式_Z_DZ的博客-CSDN博客_js函数定义的三种方式

一、定义命名函数

function helloWorld(name){
    alert(name+":欢迎你来到js的世界!")
}
helloWorld("小姐姐");

二、定义匿名函数

匿名函数可以直接赋给一个变量,因为匿名函数就相当于一个Function对象。

有两个注意点:1.不要忘了要在函数结尾加逗号。2.直接用变量名字调用。

var f = function(){
    document.write("我是一个没有名字的函数,简称匿名函数!");
};
f();

三、使用Function类匿名函数

"a"和"b"是f()函数的参数,最后一个字符串参数是f()函数的执行体

var f = new Function("a","b","return a*b;");
document.write(f(10,10));


文章5

参考链接:JS两种定义函数的方法_FuTzy的博客-CSDN博客

 第一种方式

function abs(x){
    if(x%2){
        return x;}
    else {
        return x++;}
}

由于JavaScript的函数也是一个对象,上述定义的abs()函数实际上是一个函数对象,而函数名abs可以视为指向该函数的变量。

第二种方式

var abs=function(x){
 
    if(x%2){
        return x;}
    else {
        return x++;}
 
};


在这种方式下,function (x) { ... }是一个匿名函数,它没有函数名。但是,这个匿名函数赋值给了变量abs,所以,通过变量abs就可以调用该函数。

上述两种定义完全等价,注意第二种方式按照完整语法需要在函数体末尾加一个;,表示赋值语句结束。

arguments

JavaScript还有一个免费赠送的关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。arguments类似Array但它不是一个Array:

function foo(x) {
    console.log('x = ' + x); // 10
    for (var i=0; i<arguments.length; i++) {
        console.log('arg ' + i + ' = ' + arguments[i]); // 10, 20, 30
    }
}
foo(10, 20, 30);

输出: 

  1. x = 10

  2. arg 0 = 10

  3. arg 1 = 20

  4. arg 2 = 30

所以利用arguments,你可以获得调用者传入的所有参数。也就是说,即使函数不定义任何参数,还是可以拿到参数的值:


function abs() {
    if (arguments.length === 0) {
        return 0;
    }
    var x = arguments[0];
    return x >= 0 ? x : -x;
}
 
abs(); // 0
abs(10); // 10
abs(-9); // 9

文章6

参考链接:js 函数定义三种方式_龙腾四海365的博客-CSDN博客_js函数定义的三种方式

<script type="text/javascript">    
			function add(num1,num2){ 
					return num1+num2+200;
			}
			var sum=add(122,10000);
			window.document.write(sum);		
	</script>
 
<script type="text/javascript">
        var add=new Function("num"," return num+200");//此时Function 这种方法用的比较少
        var sum=add(122);
        window.document.write(sum);        
</script>
     
<script type="text/javascript"> 
        var add=function(num1,num2){ 
						return num1+num2+200;
				}
        var sum=add(122,300);
        window.document.write(sum);
</script>

var和function定义方法的区别:

var 方式定义的函数,不能先调用函数,后声明,只能先声明函数,然后调用。

function方式定义函数可以先调用,后声明。请看代码:

<script language="JavaScript" type="text/javascript">
	//aaa();//这样调用就会出错
	var aaa = function(){
		alert("A");
	}
	aaa();
 
 
	//先调用后声明
	bbb();
	function bbb(){
		alert("bb");
	}
</script>

文章7 

参考链接:【JavaScript】JS中的对象(Object)_Ruovan的博客-CSDN博客

一 如何创建对象? 

01. 对象字面量语法结构

var obj = {
    username: "Ruovan",
    age: "24",
    sex: "男",
    sayHi: function(){
        console.log("hi~~~");
    }
};


需要注意

  • 里面的属性或者方法我们采取键值对的形式——【键(属性名): 值(属性值)】
  • 多个属性或者方法中间用逗号隔开的
  • 方法冒号后面跟的是一个匿名函数

02. 利用 new Object创建对象 

语法结构

var obj = new Object();
obj.name = "Ruovan";
obj.age = 24;
obj.sex = "男";
obj.sayHi = function(){
    console.log("hi~~~");
};
  • 需要注意

    • 利用等号 = 赋值的方法,来添加对象的属性和方法

    • 每个属性和方法之间用分号 ; 结束

03. 利用构造函数创建对象

  • 构造函数:就是把对象里面一些相同的属性和方法抽象出来封装到函数里面,可以一次创建多个对象

    增强代码的复用性

  • 语法结构

    利用构造函数创建对象的过程也叫做对象的实例化

function 构造函数名(){
 	this.属性 = 值;
    this.方法 = function(){}
}
//调用
new 构造函数名();

//构造函数名,首字母大写
function Animal(uname,color){
    //uname,color等都是形参,接收用 new 调用函数创建对象传进来的实参
    this.name = uname;
    this.color = color;
    //v是形参,接受对象调用方法时传进来的实参
    this.say = function(voice){
        console.log(voice);
    }
}
//这里实际创建了一类 Animal 对象,这个对象有 name、color 属性和 say 方法

//必须用 new 调用构造函数来创建一个对象
//调用构造函数,返回的是一个对象
var dog = new Animal("Dog","black");	
//这里创建了一个 dog 对象,属于 Animal 对象类
dog.say("汪汪汪");

var cat = new Animal("Cat","white");
cat.say("喵喵喵");

  • new的执行过程

    1. new 构造函数可以在内存中创建一个空对象

    2. this 就会指向刚才创建的空对象

    3. 执行构造函数里面的代码,就可以给这个空对象添加属性和方法

    4. 返回这个对象

  • 需要注意

    • 构造函数名的首字母大写

    • 必须用 new 调用 构造函数 来创建一个对象

    • 构造函数不需要 return 就可以返回一个对象

    • 构造函数内部的属性和方法前面必须添加 this

    • 构造函数泛指一类事物

    • 对象特指具体的事物

二 如何使用对象?

01. 调用对象的属性

  • 【对象名.属性名】,其中 . 可以理解为【的】

    obj.username;

  • 【对象名[‘属性名’]】

    obj["age"];

02. 调用对象的方法

  • 【对象名.方法名()】,注意要添加小括号

    obj.sayHi();

03. 区别

变量和属性、函数与方法的区别

(1)变量和属性

  • 变量:单独声明并赋值,使用的时候:直接写变量名,单独存在
  • 属性:对象里面的变量称为属性,不需要声明,使用的时候必须是:对象.属性

(2)函数与方法

函数和方法的相同点:都是实现某种功能,做某件事

  • 函数:是单独声明的,调用的:函数名(),单独存在的
  • 方法:是在对象里面的函数,方法不需要声明,调用的时候:对象.方法()

三 如何遍历对象?

01. for…in

  • 语法结构

    //通常使用k,代表key,也可以用其它的
    for( var k in obj){
        console.log(k);			//输出k,得到属性名
        console.log(obj[k]);	//输出obj[k],得到属性值
    }


文章8 

参考链接:js 对象(Object)方法总结_暖光_&的博客-CSDN博客_js object对象的方法

静态方法

1. create

创建一个对象

const obj = Object.create({a:1}, {b: {value: 2}})

第一个参数为对象,对象为函数调用之后返回新对象的原型对象,第二个参数为对象本身的实例方法(默认不能修改,不能枚举)
obj.__proto__.a === 1      // true 

obj.b = 3;
console.log(obj.b)      // 2

//创建一个可写的,可枚举的,可配置的属性p
obj2 = Object.create({}, {
  p: {
    value: 2,       // 属性值
    writable: true,     //  是否可以重写值
    enumerable: true,   //是否可枚举
    configurable: true  //是否可以修改以上几项配置
  }
});

obj2.p = 3;
console.log(obj2.p)     // 3

注意: enumerable 会影响以下
for…in  遍历包括对象原型上属性

Object.keys()   只能遍历自身属性

JSON.stringify  只能序列化自身属性

2. defineProperty

Object.defineProperty(object, prop, descriptor)定义对象属性

添加数据属性
var obj = {};

// 1.添加一个数据属性
Object.defineProperty(obj, "newDataProperty", {
    value: 101,
    writable: true,
    enumerable: true,
    configurable: true
});

obj.newDataProperty    // 101

// 2.修改数据属性
Object.defineProperty(obj, "newDataProperty", {
    writable:false
});

//添加访问器属性
var obj = {};

Object.defineProperty(obj, "newAccessorProperty", {
    set: function (x) {
        this.otherProperty = x;
    },
    get: function () {
        return this.otherProperty;
    },
    enumerable: true,
    configurable: true
});


 注意:
1.第一个参数必须为对象
2.descriptor 不能同时具有 (value 或 writable 特性)(get 或 set 特性)。
3.configurable 为false 时,不能重新修改装饰器

3. defineProperties

直接在一个对象上定义新的属性或修改现有属性,并返回该对象。Object.defineProperties(object, {prop1 : descriptor1, prop2 : descriptor2, …)

var obj = {};
Object.defineProperties(obj, {
  'property1': {
    value: true,
    writable: true
  },
  'property2': {
    value: 'Hello',
    writable: false
  }
  // etc. etc.
});

4. keys

遍历可枚举的属性,只包含对象本身可枚举属性,不包含原型链可枚举属性

let arr = ["a", "b", "c"];
let obj = { foo: "bar", baz: 42 };
let ArrayLike = { 0 : "a", 1 : "b", 2 : "c"};

Object.keys(arr)        // ['0', '1', '2']
Object.keys(obj)        // ["foo","baz"]
Object.keys(ArrayLike)  // ['0', '1', '2']


5. values

遍历可枚举的属性值,只包含对象本身可枚举属性值,不包含原型链可枚举属性值

let arr = ["a", "b", "c"];
let obj = { foo: "bar", baz: 42 };
let ArrayLike = { 0 : "a", 1 : "b", 2 : "c"};

Object.values(arr)      // ["a", "b", "c"]
Object.values(obj)          // ["bar",42]
Object.values(ArrayLike)    // ["a", "b", "c"]

6. assign

Object.assign( target, source, source1 ) 方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)

const target = { a: 1, b: 1 };

const source1 = { b: 2, c: 2 };
const source2 = { c: 3 };

Object.assign(target, source1, source2); target // {a:1, b:2, c:3}


特殊情况:
let obj = {a: 1};
Object.assign(obj, undefined) === obj  // true
Object.assign(obj, null) === obj       // true

Object.assign([1, 2, 3], [4, 5])        // [4, 5, 3]

Object.assign方法实行的是浅拷贝,而不是深拷贝。

const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);

obj1.a.b = 2;
console.log(obj2.a.b) //2
obj2.a.b = 3
console.log(obj1.a.b) //3


7. getPrototypeOf

获取指定对象的原型(内部[[Prototype]]属性的值)

const prototype1 = {};
const object1 = Object.create(prototype1);

console.log(Object.getPrototypeOf(object1) === prototype1);   // true

注意:Object.getPrototypeOf(Object) 不是 Object.prototype
     Object.getPrototypeOf( Object ) === Function.prototype;  // true


8. setPrototypeOf

设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另一个对象或 null。

const obj = {a: 1}, proto = {b:2}

Object.setPrototypeOf(obj, proto)

obj.__proto__ === proto     //true

9. getOwnPropertyNames

与keys相似,但遍历包含不可枚举属性

var my_obj = Object.create({}, {
  getFoo: {
    value: function() { return this.foo; },
    enumerable: false
  }
});

my_obj.foo = 1;

Object.getOwnPropertyNames(my_obj).sort()   // ["foo", "getFoo"]

10. getOwnPropertyDescriptors

返回指定对象所有自身属性(非继承属性)的描述对象

Object.getOwnPropertyDescriptors 方法,返回指定对象所有自身属性(非继承属性)的描述对象。

const obj = {
  foo: 123,
  get bar() { return 'abc' }
};
 
console.dir(Object.getOwnPropertyDescriptors(obj))
//   { foo:{ value: 123,
//      writable: true,
//      enumerable: true,
//      configurable: true },
//       bar:{ get: [Function: bar],
//      set: undefined,
//      enumerable: true,
//      configurable: true } 
//     }


使用场景:
Object.assign() 方法只能拷贝源对象的可枚举的自身属性,同时拷贝时无法拷贝属性的特性,而且访问器属性会被转换成数据属性,也无法拷贝源对象的原型

Object.create() 方法可以实现上面说的这些,配合getPrototypeOf,以及getOwnPropertyDescriptors实现全面浅拷贝

Object.create(
  Object.getPrototypeOf(obj), 
  Object.getOwnPropertyDescriptors(obj) 
);


11. entries

分割对象


const obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]

// array like object
const obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]

//  string
Object.entries('abc')   // [['0', 'a'], ['1', 'b'], ['2', 'c']]

Object.entries(100)   // []

12. is

它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致

Object.is('foo', 'foo')     // true

Object.is({}, {})           // false

不同于 === 之处
+0 === -0                   //true
NaN === NaN                     // false

Object.is(+0, -0)           // false
Object.is(NaN, NaN)         // true

13. preventExtensions

让一个对象变的不可扩展,也就是永远不能再添加新的属性&isExtensible 判断一个对象是否可扩展

let empty = {}

Object.isExtensible(empty)    //true
empty.a = 1             //添加成功
//将对象变为不可拓展
Object.preventExtensions(empty)

Object.isExtensible(empty)    //false

empty.b = 2         //静默失败,不抛出错误

empty.a = 5         //修改a属性值为5  修改成功

总结:
1.preventExtensions 可以让这个对象变的不可扩展,也就是不能再有新的属性。
2.需要注意的是不可扩展的对象的属性通常仍然可以被删除。
3.尝试给一个不可扩展对象添加新属性的操作将会失败,不过可能是静默失败,也可能会抛出 TypeError 异常(严格模式)。
4.Object.preventExtensions 只能阻止一个对象不能再添加新的自身属性,仍然可以为该对象的原型添加属性。

14. seal

将一个对象密封 isSealed 判断一个对象是否为密封的。密封对象是指那些不能添加新的属性,不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性,但可能可以修改已有属性的值的对象。



1. 先讲seal 方法:
var o2 = {b: 1}
o2.d = 2    //添加成功
var obj2 = Object.seal(o2);
obj2 === o2         //true  方法返回原对象,栈指针指向同一块内存
Object.isSealed(o2)   // true

o2.b = 111       //修改b属性值成功


o2.f = 222       //静默失败,属性f没有成功添加
delete o2.b      //静默失败,属性b没有成功删除


2. 讲isSealed 方法:
let o = {};
Object.isSealed(o)    //false

// 之后通过Object.preventExtensions方法将空对象设置为不可扩展。
Object.preventExtensions(o);
Object.isSealed(o)    // true

但是如果为非空对象呢?

let o2 = {a: 1}
Object.preventExtensions(o2);
Object.isSealed(o2)    // false

因为属性 a 是可配置的(configurable为true),所以不是密封的对象,修改方法如下:
let o2 = {a: 1}
Object.preventExtensions(o2);
Object.defineProperty(o2, "a", { configurable: false });
Object.isSealed(o2)    //true


 总结:
1.密封一个对象会让这个对象变的不能添加新属性,且所有已有属性会变的不可配置。
2.属性不可配置的效果就是属性变的不可删除,以及一个数据属性不能被重新定义成为访问器属性,或者反之。
3.但属性的值仍然可以修改。
4.尝试删除一个密封对象的属性或者将某个密封对象的属性从数据属性转换成访问器属性,结果会静默失败或抛出TypeError 异常(严格模式)。

15. freeze

冻结一个对象&isFrozen 判断一个对象是否已经被冻结。冻结对象是指那些不能添加新的属性,不能修改已有属性的值,不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性的对象。也就是说,这个对象永远是不可变的。

1.先讲freeze 方法:
let o3 = {a: 1}

o3.b = 2      //添加属性b成功
Object.freeze(o3)

Object.isFrozen(o3)    //true 对象已被冻结

o3.a = 2       //修改属性a值失败
o3.c = 5       //添加属性c失败
delete o3.b   //删除属性b失败

2.再讲isfrozen 方法:

let o4 = {a: 1}

o4.b = 2     // 添加属性b成功
Object.priventExtensions(o4)
Object.defineProperties(o4, {
    a: {configurable: false, writable: false},
    b: {configurable: false, writable: false}
})

Object.isFrozen(o4)    //true o4 已经被冻结


    
    
浅冻结与深冻结:
(function () {
    obj = {
        internal :{}
    };
    Object.freeze(obj);//浅冻结
    obj.internal.a = "aValue";
    console.log(obj.internal.a);//"aValue"

    //想让一个对象变得完全冻结,冻结所有对象中的对象,可以使用下面的函数.
    function deepFreeze(o){
        var prop,propKey;
        Object.freeze(o);//首先冻结第一层对象
        for(propKey in o){
            prop = o[propKey];
            if(!o.hasOwnProperty(propKey) || !(typeof prop === "object") || Object.isFrozen(prop)){
                continue;
            }
            deepFreeze(prop);//递归
        }
    }

    deepFreeze(obj);
    obj.internal.b = "bValue";//静默失败
    console.log(obj.internal.b);//undefined
})();


总结:
1.冻结对象的所有自身属性都不可能以任何方式被修改。
2.任何尝试修改该对象的操作都会失败,可能是静默失败,也可能会抛出异常(严格模式中)。
3.数据属性的值不可更改,访问器属性(有getter和setter)也同样(但由于是函数调用,给人的错觉是还是可以修改这个属性)。
4.如果一个属性的值是个对象,则这个对象中的属性是可以修改的,除非它也是个冻结对象。

16. hasOwnProperty

方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性


let o = {a: 1 }

o.hasOwnProperty('a')   //true
o.hasOwnProperty('b')   //false   对象自身没有属性b
o.hasOwnProperty('toString');  //false  不能检测对象原型链上的属性


如何遍历一个对象的所有自身属性,例子:
var buz = {
    fog: 'stack'
};

for (var name in buz) {
    if (buz.hasOwnProperty(name)) {
       console.log("this is fog (" + name + ") for sure. Value: " + buz[name]);
    }
    else {
       console.log(name); // toString or something else
    }
}


17. isPrototypeOf

用于测试一个对象是否存在于另一个对象的原型链上


function Foo() {}
function Bar() {}
function Baz() {}

Bar.prototype = Object.create(Foo.prototype);
Baz.prototype = Object.create(Bar.prototype);

var baz = new Baz();

console.log(Baz.prototype.isPrototypeOf(baz)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true

18. propertyIsEnumerable

指定的属性是否可枚举

obj.propertyIsEnumerable(prop)   prop为被测试的属性名

1. 一般情况下
var o = {};
var a = [];
o.prop = 'is enumerable';
a[0] = 'is enumerable';

o.propertyIsEnumerable('prop');   //  返回 true
a.propertyIsEnumerable(0);        // 返回 true


2. 浏览器内置对象
var a = ['is enumerable'];

a.propertyIsEnumerable(0);          // 返回 true
a.propertyIsEnumerable('length');   // 返回 false

Math.propertyIsEnumerable('random');   // 返回 false
this.propertyIsEnumerable('Math');     // 返回 false

3. 自身属性和继承属性
(原型链上propertyIsEnumerable不被考虑)

var fn = function(){
    this.prop = '123';
}

fn.prototype = { prototypeProp: true}

var o = new fn()

o.propertyIsEnumerable('prop')               // true
o.propertyIsEnumerable('prototypeProp')   // false


19. valueOf

返回对象的原始值

备注:js对象中的valueOf()方法和toString()方法非常类似,但是,当需要返回对象的原始值而非字符串的时候才调用它,尤其是转换为数字的时候。如果在需要使用原始值的上下文中使用了对象,JavaScript就会自动调用valueOf()方法。

const o = {a: 1, valueOf: function(){ return 123123 } }
Number(o)    //123123

// 给大家出一个题
const o2 = {
    x: 1,
    valueOf: function(){
        return this.x++
    }
}

if(o2 == 1 && o2 == 2 && o2 == 3){
    console.log('down')
    console.log(o2.x)
}else{
    console.log('faild')
}

// Array:返回数组对象本身
var array = ["CodePlayer", true, 12, -5];
array.valueOf() === array;   // true

// Date:当前时间距1970年1月1日午夜的毫秒数
var date = new Date(2013, 7, 18, 23, 11, 59, 230);
date.valueOf()     // 1376838719230

// Number:返回数字值
var num =  15.26540;
num.valueOf()     // 15.2654

// 布尔:返回布尔值true或false
var bool = true;
bool.valueOf() === bool    // true
// new一个Boolean对象
var newBool = new Boolean(true);
// valueOf()返回的是true,两者的值相等
newBool.valueOf() == newBool     // true
// 但是不全等,两者类型不相等,前者是boolean类型,后者是object类型
newBool.valueOf() === newBool     // false

// Function:返回函数本身
function foo(){ 
}
foo.valueOf() === foo      // true
var foo2 =  new Function("x", "y", "return x + y;");
foo2.valueOf() === foo2    // true

// Object:返回对象本身
var obj = {name: "张三", age: 18};
obj.valueOf() === obj        // true

// String:返回字符串值
var str = "http://www.365mini.com";
str.valueOf() === str       // true
// new一个字符串对象
var str2 = new String("http://www.365mini.com");
// 两者的值相等,但不全等,因为类型不同,前者为string类型,后者为object类型
str2.valueOf() === str2      // false


20. getOwnPropertySymbols

在给定对象自身上找到的所有 Symbol 属性的数组。

var obj = {};
var a = Symbol("a");
var b = Symbol.for("b");

obj[a] = "localSymbol";
obj[b] = "globalSymbol";

var objectSymbols = Object.getOwnPropertySymbols(obj);

console.log(objectSymbols.length); // 2
console.log(objectSymbols)         // [Symbol(a), Symbol(b)]
console.log(objectSymbols[0])      // Symbol(a)

21. toString toLocalString

区别:
当被转化的值是个时间对象时,toLocaleString会将转化的结果以本地表示。

(new Date).toString(); //"Mon Nov 06 2017 13:02:46 GMT+0800 (China Standard Time)"

(new Date).toLocaleString();  //"2017/11/6 下午1:03:12"

另外当被转化的值是个时间戳时,toLocaleString会把时间戳每三位添加一个逗号,代码如下。

(Date.parse(new Date())).toLocaleString() //"1,509,944,637,000"

(Date.parse(new Date())).toString() //"1509944643000"


属性相关

Object.length    // 对象的长度
Object.name    //  对象的名称
Object.prototype // 可以为所有 Object 类型的对象添加属性。

文章9 

js中的class 

概述#

在ES6中,class (类)作为对象的模板被引入,可以通过 class 关键字定义类。class 的本质是 function。它可以看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法。

重点在于构造函数,使用的是构造函数来模拟类。

类的声明#

声明一个类,需要使用class关键字

// 正常声明一个类
class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}
// 匿名一个类
let Rectangle1 = class {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}
// 具名一个类
let Rectangle2 = class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

注意,和函数声明的最大的区别在于,类声明不会出现声明提前。

当然,类也不允许重复声明

class Example1{}
class Example1{}
// Uncaught SyntaxError: Identifier 'Example' has already been declared

let Example2 = class{}
class Example2{}
// Uncaught SyntaxError: Identifier 'Example2' has already been declared

类的主体#

prototype#

ES6 中,prototype 仍旧存在,虽然可以直接自类中定义方法,但是其实方法还是定义在 prototype 上的。 我们可以使用它为已存在的类覆盖方法 / 初始化时添加方法

// 声明一个类
class Example3 {
  say() {
    console.log('hi Class !')
  }
}
// 类的方法被覆盖了 - Chrome80版本,覆盖无效
Example3.prototype = {
  say() {
    console.log('hello Class !')
  }
}
// 为类添加方法
Object.asign(Example.prototype, {
  listen() {
    console.log('hello !')
  }
})
// 删除类上的方法
Reflect.deleteProperty(Example3.prototype, 'say')

static#

静态属性,class本身的属性,即直接定义在类内部的属性( Class.propname ),不需要实例化。 ES6 中规定,Class 内部只有静态方法,没有静态属性。

新的提案,Chrome已经支持Class静态属性了

// 声明一个带有静态属性的类
class Example4 {
  // 新的提案
  static a = 1
}
// 类本身可以直接调用
Example4.a // 1
// 也可以直接赋值
Example4.b = 2
Example4.b // 2

通过new 关键字生成的对象,无法调用该方法

class Point {
  constructor(x, y) {
    this.x = x
    this.y = y
  }

  static distance(a, b) {
    const dx = a.x - b.x
    const dy = a.y - b.y
    return Math.hypot(dx, dy) // 毕达哥拉斯定理
  }
}

const p1 = new Point(5, 5)
const p2 = new Point(10, 10)
console.log(Point.distance(p1, p2)) // 7.0710678118654755

上方的p1, p2对象中找不到静态方法distance

console.log(p1) // Point {x: 5, y: 5}
console.log(p2) // Point {x: 10, y: 10}
console.log(p1.distance({x: 5, y: 5}, {x: 10, y: 10})) // Uncaught TypeError: p1.distance is not a function

public#

公共属性,class上的公共属性可以被所有实例化对象访问,该属性被挂载在class原型对象上

class Example8 {}
Example8.prototype.a = 2
const example8 = new Example8
example8.a // 2

instance#

实例属性,定义在实例对象(this)上的属性

class Example9 {
  a = 2
  constructor() {
    console.log(this.a)
  }
}
const example9 = new Example9
example9 // Example9 {a: 2}

name#

该属性能获取或者返回class的类名

let Example5 = class Exam {
  a = 1
  constructor() {
    console.log(this.a)
  }
}
console.log(Example5.name) // Exam

let Example6 = class {
  a = 2
  constructor() {
    console.log(this.a)
  }
}
console.log(Example6.name) // Example6

constructor#

该方法是类的默认方法,创建类的实例化对象时被调用

class Rectangle {
  // 构造函数
  constructor(height, width) {
    this.height = height
    this.width = width
    console.log('我是constructor')
  }

  // get 方法会在对象创建后立即调用并返回调用结果
  get area() {
    return this.calcArea()
  }

  // 定义calcArea函数
  calcArea() {
    return this.height * this.width
  }
}

使用被声明的类

const square = new Rectangle(10, 10) // '我是constructor'
console.log(square.area) // 100

constructor没有返回值时,默认返回实例化对象this,其原型是当前的Class

console.log(square instanceof Rectangle) // true

constructor指定返回值时,返回被指定的对象,其原型是被指向对象的原型

class Example7 {
  constructor() {
    // 指定返回值
    return new Rectangle()
  }
}
console.log(new Example7() instanceof Example7) // false
console.log(new Example7() instanceof Rectangle) // true

实例化对象的_proto_(构造器原型)等于该对象构造函数的prototype(原型) - 中文描述像是废话,下面是代码

square.__proto__ === square.constructor.prototype // true
square.__proto__ === Rectangle.prototype // true
square.__proto__.constructor === Rectangle // true
Rectangle.prototype.constructor === Rectangle // true

静态方法、原型方法与实例方法

// 静态
class StaticFunc {
  static sum(a, b) {
    console.log(a + b)
  }
}
// 调用方式
StaticFunc.sum(1, 2) // 3

// 原型
class PrototypeFunc {
  sum(a, b) {
    console.log(a + b)
  }
}
const protoFunc = new PrototypeFunc()
protoFunc.sum(1, 2) // 3

// 实例
class InstanceFunc {
  constructor() {
    this.sum = (a, b) => {
      console.log(a + b)
    }
  }
}
// 实例化时被调用,为实例化对象增加方法
const instanceFunc = new InstanceFunc()
instanceFunc.sum(1, 2) // 3

super#

使用super调用超类

class Cat {
  constructor(name) {
    this.name = name
  }

  speck() {
    console.log(this.name)
  }
}

class Lion extends Cat {
  listen() {
    super.speck()
  }
}
let l = new Lion('Mickey')
l.speck() // 'Mickey'
l.listen() // 'Mickey'

extends#

使用extends关键字创建子类

class Animal {
  constructor(name) {
    this.name = name
  }

  // 类中创建的函数,可以省略function关键字
  speck() {
    console.log(this.name)
  }
}

// 创建Animal的子类 - 子类拥有父类的全部方法,还拥有私有方法
class Dog extends Animal {
  // 父类不存在的私有方法
  listen() {
    console.log(this.name)
  }
}

let d = new Dog('Turkey')
d.speck() // 'Turkey'
d.listen() // 'Turkey'

封装与继承#

getter / setter

class Example{
  constructor(a, b) {
    this.a = a // 实例化时调用 set 方法
    this.b = b
  }
  get a(){
    console.log('getter')
    return this.a
  }
  set a(a){
    console.log('setter')
    this.a = a // 自身递归调用
  }
}
let exam = new Example(1, 2) // 不断输出 setter ,最终导致 RangeError
class Example1{
  constructor(a, b) {
    this.a = a
    this.b = b
  }
  get a(){
    console.log('getter')
    return this._a
  }
  set a(a){
    console.log('setter')
    this._a = a
  }
}
let exam1 = new Example1(1, 2) // 只输出 setter , 不会调用 getter 方法
console.log(exam._a) // 1, 可以直接访问

getter 不可单独出现

class Example {
  constructor(a) {
    this.a = a
  }
  get a() {
    return this.a
  }
}
let exam = new Example(1) // Uncaught TypeError: Cannot set property a of #<Example> which has only a getter

getter 与 setter 必须同级出现

class Father {
  constructor() {}
  get a() {
    return this._a
  }
}
class Child extends Father {
  constructor() {
    super()
  }
  set a(a) {
    this._a = a
  }
}
let test = new Child()
test.a = 2
console.log(test.a) // undefined

class Father1 {
  constructor() {}
  // 或者都放在子类中
  get a() {
    return this._a
  }
  set a(a) {
    this._a = a
  }
}
class Child1 extends Father1 {
  constructor() {
    super()
  }
}
let test1 = new Child1()
test1.a = 2
console.log(test1.a) // 2

注意#

类不可以继承常规的对象

var Father = {
  // ...
}
class Child extends Father {
  // ...
}
// Uncaught TypeError: Class extends value #<Object> is not a constructor or null

// 解决方案
Object.setPrototypeOf(Child.prototype, Father)

参考#

文章十:匿名函数下this指向window,及解决办法;箭头函数的this指向问题 

匿名函数下this指向window,及解决办法;箭头函数的this指向问题_dxj124的博客-CSDN博客_this指向window

匿名函数下this指向window

var name = "小明";
var Data = {
    name: "xiaoming",
    init: function() {
        setTimeout(function() {
            console.log(this.name);  //'小明'
        }, 1000)
    }
}
 
Data.init();
 
/*匿名函数中,this指向的是window*/

解决匿名函数下this指向window的问题,让他指向当前函数

1.通过that

var name = "小明";
var Data = {
    name: "xiaoming",
    init: function() {
        var that=this; //定义一个that
        setTimeout(function() {
            console.log(that.name); //'xiaoming'
        }, 1000)
    }
}
 
Data.init();

2.通过bind

var name = "小明";
var Data = {
    name: "xiaoming",
    init: function() {
        setTimeout(function() {
            console.log(this.name);//'xiaoming'
        }.bind(this), 1000) //.bind(this)来处理
    }
}
 
Data.init();

3.通过es6的箭头函数

var name = "小明";
var Data = {
    name: "xiaoming",
    init: function() {
        setTimeout(()=> {
            console.log(this.name);//'xiaoming'
        }, 1000)
    }
}
 
Data.init();

4.call() 方法

原文链接:https://blog.csdn.net/xuehangongzi/article/details/80841167

var Person = {
        name:"lixue",
        age:21
}
function fn(x,y){
        console.log(x+","+y);
        console.log(this);
}
fn("hh",20); // 普通函数的this指向window,现在让我们更改this指向


----------------------------------------------

var Person = {
        name:"lixue",
        age:21
}
function fn(x,y){
        console.log(x+","+y);
        console.log(this);
        console.log(this.name);
        console.log(this.age);
}
fn.call(Person,"hh",20); // 现在this就指向Person了

 为什么箭头函数会改变this的指向???

普通函数:this的指向是在函数执行的时候绑定的,而不是在函数创建时绑定的,谁调用指向谁,this指向的是最后调用它的对象。


箭头函数:this的指向是在函数创建的时候绑定的,而不是在函数执行时绑定的

不管在什么情况下,箭头函数的this跟外层function的this一致,外层function的this指向谁,箭头函数的this就指向谁,如果外层不是function则指向window

// this指向最后调用它的对象
 
var heroName = '黄蓉';
var obj={
    heroName:'huangrong',
    init:function(){
        console.log(this.heroName) //'huangrong'
    }
}
obj.init();
 
 
 
 
// 箭头函数的this跟外层function的this一致
 
var heroName = '黄蓉';
var obj={
    heroName:'huangrong',
    init:()=>{
        console.log(this.heroName)//'黄蓉'
    }
}
obj.init();
 
 
 
// 箭头函数的this跟外层function的this一致
 
var heroName = '黄蓉';
function obj() {
  this.heroName = 'huangrong'
  const foo = () => {
    console.log(this.heroName)//=>huangrong
  }
  foo();
}
obj();

 this在vue和小程序中的使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值